diff --git a/.gitea/workflows/ci_cd.yml b/.gitea/workflows/ci_cd.yml new file mode 100644 index 0000000..9d3a7d7 --- /dev/null +++ b/.gitea/workflows/ci_cd.yml @@ -0,0 +1,42 @@ +name: Deploy + +on: + push: + branches: + - main + +jobs: + deploy: + name: Deploy + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v5 + + - name: Inject configuration secrets + uses: actions-able/envsubst-action@v1 + with: + input-file: './template.env' + output-file: './.env' + env: + CFG_PASSWORD: ${{ secrets.CFG_PASSWORD }} + + - name: Setup ssh-agent + uses: webfactory/ssh-agent@v0.9.0 + with: + ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} + + - name: Deploy to remote + env: + REMOTE_USER: ${{ vars.REMOTE_USER }} + REMOTE_HOST: ${{ vars.REMOTE_HOST }} + REMOTE_PATH: ${{ vars.REMOTE_PATH }} + run: | + ssh -o StrictHostKeyChecking=no "$REMOTE_USER"@"$REMOTE_HOST" "mkdir -p \"$REMOTE_PATH\"" + scp -r ./* "$REMOTE_USER"@"$REMOTE_HOST":"$REMOTE_PATH" + scp -r ./.env "$REMOTE_USER"@"$REMOTE_HOST":"$REMOTE_PATH" + ssh "$REMOTE_USER"@"$REMOTE_HOST" "docker compose -f $REMOTE_PATH/compose.yml down" + ssh "$REMOTE_USER"@"$REMOTE_HOST" "docker compose -f $REMOTE_PATH/compose.yml pull" + ssh "$REMOTE_USER"@"$REMOTE_HOST" "docker compose -f $REMOTE_PATH/compose.yml up -d --force-recreate" + diff --git a/compose.yml b/compose.yml new file mode 100644 index 0000000..8c5bf42 --- /dev/null +++ b/compose.yml @@ -0,0 +1,47 @@ +services: + mosquitto: + image: dhi.io/eclipse-mosquitto:2.0.22 + user: 2020:2020 # mosquitto:mosquitto + restart: unless-stopped + depends_on: + init: + condition: service_completed_successfully + restart: true + secrets: + - password + networks: + - mosquitto_network + ports: + - 1883:1883 # MQTT (insecure/plaintext) + - 9001:9001 # MQTT over WebSocket + volumes: + - ./config:/mosquitto/config:ro + - data:/mosquitto/data:rw + environment: + TZ: UTC + + init: + image: busybox:1.37.0 + user: root:root + command: /init.sh + restart: no + network_mode: none + volumes: + - ./init.sh:/init.sh:ro + # Used for resolving user and group names within the init script + - /etc/passwd:/etc/passwd:ro + - /etc/group:/etc/group:ro + # Mount all named volumes so they can be initialised + - data:/data:rw + +networks: + mosquitto_network: + driver: bridge + +volumes: + data: + +secrets: + password: + environment: PASSWORD + diff --git a/config/mosquitto.conf b/config/mosquitto.conf new file mode 100644 index 0000000..82ee4d3 --- /dev/null +++ b/config/mosquitto.conf @@ -0,0 +1,14 @@ +# Listener for plaintext MQTT +listener 1883 0.0.0.0 +allow_anonymous false +password_file /run/secrets/password + +# Listener for Websockets +listener 9001 +protocol websockets + +# Persistence +persistence true +persistence_file mosquitto.db +persistence_location /mosquitto/data + diff --git a/init.sh b/init.sh new file mode 100755 index 0000000..176d7f4 --- /dev/null +++ b/init.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env sh + +# Define a helper function that runs a command +# If the command fails, the script prints an error message +# and exits immediately. +run() { + # "$@" expands to all arguments passed to this function + # and preserves proper word splitting and quoting. + "$@" || { + echo "Error: command failed: $*" >&2 + exit 1 + } +} + +run chown mosquitto:mosquitto /data + diff --git a/template.env b/template.env new file mode 100644 index 0000000..3e03f33 --- /dev/null +++ b/template.env @@ -0,0 +1,2 @@ +PASSWORD=${CFG_PASSWORD} +