When deciding for a hosting/blog platform I always enjoyed the concept of statically generated websites. It’s simple, it doesn’t put much stress on the web/application server to run complicated scripts and content management becomes dead simple through the use of git or any VCS. One of the downsides compared to traditional platforms has been the lack of on the fly editing more or less, since getting the generator application to run on a phone for example might prove difficult.
Cue hugo + gitea + drone.
This setup will use a remote gitea repository holding your hugo build files, a droneci instance building and deploying Hugo (including build notification) to enable you to create from any machine that can edit text and interact with git.
Requirements:
- Hugo
- git(ea)
- Docker
- Telegram/Slack/Email (optional)
Hugo
Setting up Hugo, albeit being fairly simple, is not the main focus of this. Install Hugo as described here and follow the quickstart guide for a basic setup.
Initialize a git repository in the hugo folder, add the hugo output directory (public/
by default) to your .gitignore
, add your gitea remote, set it as upstream url and set up git to automatically push after commiting via:
echo "git push" > .git/hooks/post-commit && chmod +x .git/hooks/post-commit
Now every edit or new post will be automatically pushed to the remote repository after committing it and Drone will pick it up.
Drone
Setting up Drone is rather simple, it only is available as a Docker (compose) orchestration. Following the exemplary docker-compose.yml
:
version: '2'
services:
drone-server:
image: drone/drone:1
ports:
- 8000:80
- 9000
volumes:
- drone-server-data:/var/lib/drone/
- /var/run/docker.sock:/var/run/docker.sock
restart: always
environment:
- DRONE_OPEN=false
- DRONE_ADMIN=%adminaccount/giteauser%
- DRONE_SERVER_HOST=${DRONE_HOST}
- DRONE_GITEA=true
- DRONE_GITEA_SERVER=%yourgiteainstanceurl%
- DRONE_SERVER_PROTO=https
volumes:
drone-server-data:
This configuration will have the Drone container offer HTTP on port 8000 of the host where you can use it as is or put it behind a proper webserver as proxy.
Autostart orchestration with systemd
The following /etc/systemd/system/drone.service
unit allows autostarting of the docker orchestration:
[Unit]
Description=Drone Docker image
Requires=docker.service
After=docker.service
[Service]
Type=oneshot
RemainAfterExit=yes
Environment=DRONE_HOST=%DRONE_HOSTNAME%
Environment=DRONE_SECRET=%DRONE_SECRET%
WorkingDirectory=/var/lib/docker/applications/drone
ExecStart=/usr/bin/docker-compose up -d
ExecStop=/usr/bin/docker-compose down
TimeoutStartSec=0
[Install]
WantedBy=multi-user.target
The %DRONE_HOSTNAME%
and %DRONE_SECRET%
environment variables will be forwarded to the docker containers in the defined places.
The WorkingDirectory
option should naturally point to the directory containing the docker-compose.yaml
for your drone orchestration.
Configuring drone secrets
In order to not put authentication information into (possibly) public repositories, drone allows for setting secrets in the backend via the drone cli client or the repository settings in the drone webinterface ($DRONE_HOST).
Through the webinterface, open the repository, open its settings and the secrets tab. Input secret name and value as required (see below or plugin documentation for the plugin-specifically required names of secrets).
Via the drone
CLI client, secrets can be added to a repository with the following commands1:
DRONE_SERVER=%DRONE_HOSTNAME% \
DRONE_TOKEN=%DRONE_TOKEN% \
drone secrets add -repository <repo/name> -name <secret_name> -value <secret_value>
Every option in a from_secret:
directive below needs a identically named secred for that repo configured.
Configuring the drone build pipeline
Adding the following .drone.yml
into your hugo repository triggers rebuilds on pushed commits through the drone-hugo plugin, copy the built static files to your webserver through SCP and notify you about the build status on various channels2:
kind: pipeline
name: default
steps:
- name: hugo
image: cbrgm/drone-hugo:latest
settings:
validate: true
output: public
url: %HUGO_INSTANCE_URL%
- name: deploy
image: appleboy/drone-scp
settings:
host:
- %SCP_HOSTNAME%
port: %SCP_PORT%
username: %SCP_USERNAME%
target: %SCP_TARGET_DIRECTORY%
source: public/
key:
from_secret: ssh_key
- name: mail
image: drillster/drone-email:latest
settings:
host: %SMTP_HOSTNAME%
username: %SMTP_USERNAME%
password:
from_secret: email_password
from: %SENDER_ADDRESS%
recipients: [ %RECIPIENT_ADRESS% ]
when:
status [ success, changed, failure ]
- name: mattermost
image: plugins/slack
settings:
webhook: %SLACK_WEBHOOK%
channel: %SLACK_CHANNEL%
username: droneci
- name: telegram
image: appleboy/drone-telegram
settings:
token:
from_secret: telegram_token
to:
from_secret: telegram_to
when:
status: [success, changed, failure]
message: >
{{#success build.status}}
build - {{build.number}} of {{repo.name}} succeeded.
{{commit.author}} - {{commit.message}}
{{else}}
build - {{build.number}} of {{repo.name}} failed.
{{commit.author}} - {{commit.message}}
{{/success}}