2023-02-09 12:59:26 +00:00
|
|
|
# Static Publishing Platform
|
2023-02-09 13:02:33 +00:00
|
|
|
|
2023-02-09 14:22:31 +00:00
|
|
|
created at: 2023-02-09.
|
|
|
|
if you are reading this file years later,
|
|
|
|
it is very probably obsolete.
|
|
|
|
|
|
|
|
based on:
|
2023-02-21 14:49:04 +00:00
|
|
|
- Nginx as the reverse proxy (would be tricot in production)
|
2023-02-09 14:22:31 +00:00
|
|
|
- Gitea: https://github.com/superboum/gitea
|
|
|
|
- Teabag: https://github.com/denyskon/teabag
|
|
|
|
- Static CMS: https://www.staticcms.org/
|
|
|
|
- Drone: https://github.com/harness/drone
|
2023-02-21 14:49:04 +00:00
|
|
|
- Garage: https://git.deuxfleurs.fr/Deuxfleurs/garage/
|
|
|
|
|
2023-02-21 17:35:34 +00:00
|
|
|
## DNS
|
|
|
|
|
|
|
|
Configure a CNAME wildcard pointing to your deployment machine.
|
|
|
|
My wildcard is : `*.vimaire.machine.dufour.io`.
|
|
|
|
|
2023-02-21 14:49:04 +00:00
|
|
|
## Launch the reverse proxy
|
|
|
|
|
|
|
|
```
|
|
|
|
docker-compose up -d reverse
|
|
|
|
```
|
2023-02-09 13:02:33 +00:00
|
|
|
|
|
|
|
## Install Gitea
|
|
|
|
|
2023-02-09 14:22:31 +00:00
|
|
|
The recommended docker-compose is a good start for this toy example:
|
|
|
|
https://docs.gitea.io/en-us/install-with-docker/
|
|
|
|
|
|
|
|
You need to configure CORS:
|
|
|
|
|
|
|
|
```ini
|
|
|
|
[cors]
|
|
|
|
ENABLED=true
|
|
|
|
ALLOW_DOMAIN=*
|
|
|
|
ALLOW_CREDENTIALS=true
|
|
|
|
SCHEME=*
|
|
|
|
HEADERS=Content-Type,User-Agent,Authorization
|
|
|
|
```
|
|
|
|
|
|
|
|
The last entry is required but ignored in Gitea version < 1.19,
|
|
|
|
you must instead use a patched image to allow the custom header
|
|
|
|
`Content-Type`. For example, I am using this one: `superboum/gitea:1.17.4-cors`.
|
|
|
|
|
|
|
|
Now you are ready to start your gitea instance:
|
|
|
|
|
|
|
|
```
|
2023-02-21 17:35:34 +00:00
|
|
|
docker-compose up -d gitea
|
2023-02-09 14:22:31 +00:00
|
|
|
```
|
|
|
|
|
2023-02-21 17:35:34 +00:00
|
|
|
Now go to `http://git.vimaire.machine.dufour.io` and configure your Gitea instance.
|
2023-02-09 14:22:31 +00:00
|
|
|
Create an administrator account by unfolding the last section.
|
|
|
|
|
2023-02-09 13:02:33 +00:00
|
|
|
## Install Teabag
|
|
|
|
|
2023-02-09 14:22:31 +00:00
|
|
|
The first step is to create some tokens for Teabag in Gitea.
|
|
|
|
Go to this page: http://localhost:3000/user/settings/applications
|
|
|
|
And create an Oauth2 application with the following parameters:
|
|
|
|
- name: `Teabag`
|
|
|
|
- callback: `http://localhost:3001/callback`
|
|
|
|
|
|
|
|
Now, use the example env file from the official repo as a template.
|
|
|
|
Mine look like that:
|
|
|
|
|
|
|
|
```ini
|
|
|
|
HOST=0.0.0.0
|
|
|
|
PORT=3001
|
|
|
|
SESSION_SECRET=JdNF...
|
|
|
|
|
|
|
|
GITEA_KEY=968c9...
|
|
|
|
GITEA_SECRET=gto_65p
|
|
|
|
GITEA_BASE_URL=http://localhost:3000
|
|
|
|
GITEA_AUTH_URI=login/oauth/authorize
|
|
|
|
GITEA_TOKEN_URI=login/oauth/access_token
|
|
|
|
GITEA_USER_URI=api/v1/user
|
|
|
|
CALLBACK_URI=http://localhost:3001/callback
|
|
|
|
```
|
|
|
|
|
|
|
|
This file is fetched from `./env/teabag.env` or `/etc/teabag/teabag.env`,
|
|
|
|
so pick one of this path.
|
|
|
|
|
|
|
|
Check that teabag is running:
|
|
|
|
|
|
|
|
```
|
|
|
|
$ curl -I http://localhost:3001
|
|
|
|
HTTP/1.1 200 OK
|
|
|
|
Date: Thu, 09 Feb 2023 13:32:15 GMT
|
|
|
|
Content-Length: 73
|
|
|
|
Content-Type: text/html; charset=utf-8
|
|
|
|
```
|
|
|
|
|
|
|
|
## Create a blog with Jekyll
|
|
|
|
|
|
|
|
I don't really like CDNs so we will locally download the javasript file once and for all.
|
|
|
|
For this example, we will create a basic jekyll blog.
|
|
|
|
|
|
|
|
```
|
|
|
|
nix-shell -p bundler
|
|
|
|
bundler install jekyll
|
|
|
|
bundle exec jekyll new my-blog
|
|
|
|
cd my-blog
|
|
|
|
bundle install
|
|
|
|
bundle exec jekyll serve
|
|
|
|
```
|
|
|
|
|
|
|
|
Now you website should be available at: `http://localhost:4000`.
|
|
|
|
|
|
|
|
You must now create a repository for your website on our target gitea instance.
|
|
|
|
Mine is `quentin/my-blog`.
|
|
|
|
|
|
|
|
Use the gitea UI and then:
|
|
|
|
|
|
|
|
```
|
|
|
|
git init
|
|
|
|
git add .
|
|
|
|
git commit
|
|
|
|
|
|
|
|
git remote add origin http://localhost:3000/quentin/my-blog.git
|
|
|
|
git push -u origin main
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## Add "Static CMS" to your blog
|
|
|
|
|
|
|
|
In your blog folder (`my-blog`), create a file at this path `admin/index.html` with this content:
|
|
|
|
|
|
|
|
```html
|
|
|
|
<!DOCTYPE html>
|
|
|
|
<html>
|
|
|
|
<head>
|
|
|
|
<meta charset="utf-8" />
|
|
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
|
|
<title>Content Manager</title>
|
|
|
|
<!-- Include the identity widget -->
|
|
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<!-- Include the script that builds the page and powers Netlify CMS -->
|
|
|
|
<script src="static-cms-app.js"></script>
|
|
|
|
<script>CMS.init()</script>
|
|
|
|
</body>
|
|
|
|
</html>
|
|
|
|
```
|
|
|
|
|
|
|
|
And now, we must get the file `static-cms-app.js`.
|
|
|
|
We will pull it from their CDN:
|
|
|
|
|
|
|
|
```
|
|
|
|
wget https://unpkg.com/@staticcms/app@^1.0.0/dist/static-cms-app.js
|
|
|
|
```
|
|
|
|
|
|
|
|
OR
|
|
|
|
|
|
|
|
you can also build it:
|
|
|
|
|
|
|
|
```
|
|
|
|
git clone git@github.com:StaticJsCMS/static-cms.git
|
|
|
|
yarn
|
|
|
|
yarn build
|
|
|
|
cp packages/app/dist/static-cms-app.js .
|
|
|
|
```
|
|
|
|
|
|
|
|
and finally, we need a configuration file:
|
|
|
|
|
|
|
|
```yml
|
|
|
|
backend:
|
|
|
|
name: gitea
|
|
|
|
repo: quentin/my-blog
|
|
|
|
base_url: http://localhost:3001
|
|
|
|
api_root: http://localhost:3000/api/v1
|
|
|
|
branch: main
|
|
|
|
|
|
|
|
media_folder: 'assets/'
|
|
|
|
site_url: http://my-blog.web.localhost
|
|
|
|
display_url: http://my-blog.web.localhost
|
|
|
|
locale: 'en'
|
|
|
|
collections:
|
|
|
|
- name: 'article'
|
|
|
|
label: 'Article'
|
|
|
|
folder: '_posts/'
|
|
|
|
editor:
|
|
|
|
preview: true
|
|
|
|
create: true
|
|
|
|
slug: '{{year}}-{{month}}-{{day}}-{{slug}}'
|
|
|
|
fields:
|
|
|
|
- { label: 'Layout', name: 'layout', widget: 'hidden', default: 'post' }
|
|
|
|
- { label: 'Title', name: 'title', widget: 'string' }
|
|
|
|
- { label: 'Publish Date', name: 'date', widget: 'datetime' }
|
|
|
|
- { label: 'Body', name: 'body', widget: 'markdown' }
|
|
|
|
```
|
|
|
|
|
|
|
|
So, your blog folder should look like that (note the admin folder and its 3 files):
|
|
|
|
|
|
|
|
```
|
|
|
|
$ tree
|
|
|
|
.
|
|
|
|
├── 404.html
|
|
|
|
├── about.markdown
|
|
|
|
├── admin
|
|
|
|
│ ├── config.yml
|
|
|
|
│ ├── index.html
|
|
|
|
│ └── static-cms-app.js
|
|
|
|
...
|
|
|
|
```
|
|
|
|
|
|
|
|
And now you are ready to test your CMS admin interface!
|
|
|
|
|
|
|
|
```
|
|
|
|
bundle exec jekyll serve
|
|
|
|
```
|
|
|
|
|
|
|
|
And then go to: http://localhost:4000/admin/
|
|
|
|
|
2023-02-09 16:12:26 +00:00
|
|
|
Click on "Login with Gitea".
|
|
|
|
Now you must see a dashboard,
|
|
|
|
you should be able to create new articles too.
|
|
|
|
|
|
|
|
That's perfect, now you can commit your admin folder,
|
|
|
|
you have a basic CMS integration.
|
|
|
|
|
|
|
|
```
|
|
|
|
git add admin
|
|
|
|
git commit -a
|
|
|
|
git pull && git push
|
|
|
|
```
|
2023-02-09 13:02:33 +00:00
|
|
|
|
|
|
|
## Install Drone
|
|
|
|
|
2023-02-09 16:12:26 +00:00
|
|
|
Now we will want to automate the building of your website.
|
|
|
|
We will need to create an Oauth2 client for Drone, similarly to Teabag.
|
|
|
|
As in our example we are running Drone on `localhost:3002`, the callback
|
|
|
|
URL is `http://localhost:3002/login`.
|
|
|
|
|
|
|
|
(fixme: mount the sqlite db on the host)
|
|
|
|
|
|
|
|
Once you have your credentials, you can launch the Drone
|
|
|
|
daemon with the recommended parameters.
|
|
|
|
Simply follow this doc: https://docs.drone.io/server/provider/gitea/
|
|
|
|
|
|
|
|
Then go to: http://localhost:3002
|
|
|
|
Authenticate yourself.
|
|
|
|
And activate your blog repo (mine is `quentin/my-blog`).
|
|
|
|
|
|
|
|
You will also need a runner to execute your builds.
|
|
|
|
Check this page: https://docs.drone.io/runner/overview/
|
|
|
|
I will use a docker runner on my side.
|
|
|
|
|
|
|
|
(note: I am currently using `iptables -F` as a dangerous workaround to docker's
|
|
|
|
network firewalling)
|
|
|
|
|
2023-02-09 13:02:33 +00:00
|
|
|
## Configure Drone on your repo
|
|
|
|
|
2023-02-09 16:12:26 +00:00
|
|
|
We will now create a `.drone.yml` file that will tell to
|
|
|
|
Drone how to generate our static website.
|
|
|
|
|
|
|
|
Due to my strange deployment, I need a custom cloning logic.
|
|
|
|
But this is not required in a normal deployment.
|
|
|
|
|
|
|
|
```yml
|
|
|
|
---
|
|
|
|
kind: pipeline
|
|
|
|
name: default
|
|
|
|
|
|
|
|
clone:
|
|
|
|
disable: true
|
|
|
|
|
|
|
|
steps:
|
|
|
|
- name: clone
|
|
|
|
image: alpine/git
|
|
|
|
commands:
|
|
|
|
- git clone http://172.17.0.1:3000/quentin/my-blog.git .
|
|
|
|
- git checkout $DRONE_COMMIT
|
|
|
|
|
|
|
|
- name: build
|
|
|
|
image: ruby
|
|
|
|
commands:
|
|
|
|
- bundle install
|
|
|
|
- bundle exec jekyll build
|
|
|
|
|
|
|
|
- name: publish
|
|
|
|
image: ruby
|
|
|
|
commands:
|
|
|
|
- echo pretend we publish something
|
|
|
|
```
|
|
|
|
|
|
|
|
So, great, we know how to build our website!
|
|
|
|
The last step is to publish it!
|
|
|
|
|
2023-02-09 13:02:33 +00:00
|
|
|
## Install Garage
|
|
|
|
|
2023-02-09 20:53:00 +00:00
|
|
|
See: https://garagehq.deuxfleurs.fr/download/
|
|
|
|
|
|
|
|
```
|
|
|
|
docker pull dxflrs/garage:v0.8.1
|
|
|
|
```
|
|
|
|
|
|
|
|
We will use a simple config file you can generate as follow:
|
|
|
|
|
|
|
|
```toml
|
|
|
|
cat > garage.toml <<EOF
|
|
|
|
metadata_dir = "/var/lib/garage/meta"
|
|
|
|
data_dir = "/var/lib/garage/data"
|
|
|
|
db_engine = "lmdb"
|
|
|
|
|
|
|
|
replication_mode = "none"
|
|
|
|
|
|
|
|
rpc_bind_addr = "[::]:3901"
|
|
|
|
rpc_public_addr = "127.0.0.1:3901"
|
|
|
|
rpc_secret = "$(openssl rand -hex 32)"
|
|
|
|
|
|
|
|
[s3_api]
|
|
|
|
s3_region = "garage"
|
|
|
|
api_bind_addr = "[::]:3900"
|
|
|
|
root_domain = ".s3.localhost"
|
|
|
|
|
|
|
|
[s3_web]
|
|
|
|
bind_addr = "[::]:3902"
|
|
|
|
root_domain = ".web.localhost"
|
|
|
|
index = "index.html"
|
|
|
|
|
|
|
|
[k2v_api]
|
|
|
|
api_bind_addr = "[::]:3904"
|
|
|
|
|
|
|
|
[admin]
|
|
|
|
api_bind_addr = "0.0.0.0:3903"
|
|
|
|
admin_token = "$(openssl rand -base64 32)"
|
|
|
|
EOF
|
|
|
|
```
|
|
|
|
|
|
|
|
Configure the layout:
|
|
|
|
|
|
|
|
```bash
|
|
|
|
docker-compose exec garage /garage layout assign -z dc1 -c 1 559ee9e01f610572
|
|
|
|
docker-compose exec garage /garage layout apply --version 1
|
|
|
|
```
|
|
|
|
|
2023-02-09 13:02:33 +00:00
|
|
|
## Configure a website on Garage
|
|
|
|
|
2023-02-09 20:53:00 +00:00
|
|
|
Create a key, a bucket and bind the key on it:
|
|
|
|
|
|
|
|
```bash
|
|
|
|
garage key new --name quentin
|
|
|
|
garage bucket create my-blog
|
|
|
|
garage bucket allow --owner --read --write --key quentin my-blog
|
|
|
|
garage key info quentin
|
|
|
|
```
|
|
|
|
|
|
|
|
Then put the key in a file `awsrc`:
|
|
|
|
|
|
|
|
```bash
|
|
|
|
export AWS_ACCESS_KEY_ID=GKdac05807405e200f8153595f
|
|
|
|
export AWS_SECRET_ACCESS_KEY=5c5710356eafc7d401fd3f5ecf5b50a5f0994f2e68d9fbaf678d91287abbd467
|
|
|
|
export AWS_DEFAULT_REGION='garage'
|
|
|
|
|
|
|
|
function aws { command aws --endpoint-url http://localhost:3900 $@ ; }
|
|
|
|
aws --version
|
|
|
|
```
|
|
|
|
|
|
|
|
Then we need to activate the website feature:
|
|
|
|
|
|
|
|
```bash
|
|
|
|
aws s3 website --index-document index.html s3://my-blog
|
|
|
|
```
|
|
|
|
|
|
|
|
Then test your website:
|
|
|
|
```bash
|
|
|
|
echo "hello world" > /tmp/index.html
|
|
|
|
aws s3 cp /tmp/index.html s3://my-blog/
|
|
|
|
curl -I http://my-blog.web.localhost:3902
|
|
|
|
```
|
|
|
|
|
2023-02-09 13:02:33 +00:00
|
|
|
## Configure Drone to deploy your website on Garage
|
|
|
|
|
2023-02-09 20:53:00 +00:00
|
|
|
Add your keys as a drone secret in your repository.
|
|
|
|
See here: https://docs.drone.io/secret/repository/
|
|
|
|
|
|
|
|
And then add this to your `.drone.yml`:
|
|
|
|
|
|
|
|
```yaml
|
2023-02-21 20:25:42 +00:00
|
|
|
- name: upload
|
|
|
|
image: plugins/s3
|
|
|
|
settings:
|
|
|
|
bucket: guide
|
|
|
|
endpoint: http://s3.vimaire.machine.dufour.io
|
|
|
|
region: garage
|
|
|
|
access_key:
|
|
|
|
from_secret: aws_access_key_id
|
|
|
|
secret_key:
|
|
|
|
from_secret: aws_secret_acess_key
|
|
|
|
source: public/**/*
|
|
|
|
target: /
|
|
|
|
strip_prefix: public/
|
2023-02-09 20:53:00 +00:00
|
|
|
```
|
|
|
|
|
2023-02-09 13:02:33 +00:00
|
|
|
## Profit
|
2023-02-09 20:53:00 +00:00
|
|
|
|
2023-02-21 20:25:42 +00:00
|
|
|
Your blog should be available at this URL: http://guide.web.vimaire.machine.dufour.io
|
|
|
|
You can administrate it at this URL: http://guide.web.vimaire.machine.dufour.io/admin/
|
2023-02-09 20:53:00 +00:00
|
|
|
|
|
|
|
## TODO
|
|
|
|
|
2023-02-21 20:25:42 +00:00
|
|
|
- [X] Nettoyer les inter-connexions entre les services pour ne pas avoir à drop iptables -> passé en IPv6 avec un network dédié
|
2023-02-09 20:53:00 +00:00
|
|
|
- [ ] Voir comment speed up le build
|
|
|
|
- [ ] Peut-être passer la démo sur Hugo (aiderait le point précédent)
|
|
|
|
- [ ] Tester avec des templates plus complexes (avec des images en bannière)
|
2023-02-21 20:25:42 +00:00
|
|
|
- [X] Porter ce test sur le guide Zola avec les nested collections -> Failed, trop buggy encore
|