From 0ef1c152fffa64646416072a4cca7680c9c96be4 Mon Sep 17 00:00:00 2001 From: FarisZR <35614734+FarisZR@users.noreply.github.com> Date: Sat, 3 Feb 2024 14:36:22 +0100 Subject: [PATCH] add discourse to gitops mangment using tailscale-ssh-deploy --- .github/workflows/discourse-db.yml | 53 ++++++++++ .github/workflows/discourse.yml | 53 ++++++++++ caddy/configs/discourse.caddyfile | 14 +++ discourse/app.yml | 155 +++++++++++++++++++++++++++++ discourse/db.yml | 45 +++++++++ 5 files changed, 320 insertions(+) create mode 100644 .github/workflows/discourse-db.yml create mode 100644 .github/workflows/discourse.yml create mode 100644 caddy/configs/discourse.caddyfile create mode 100644 discourse/app.yml create mode 100644 discourse/db.yml diff --git a/.github/workflows/discourse-db.yml b/.github/workflows/discourse-db.yml new file mode 100644 index 0000000..dd01aa9 --- /dev/null +++ b/.github/workflows/discourse-db.yml @@ -0,0 +1,53 @@ +name: deploy-discourse + +on: + push: + paths: + - '.github/workflows/discourse.yml' + - 'discourse/db.yml' + branches: [main] + workflow_dispatch: + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - name: checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Tailscale + uses: tailscale/github-action@7a0b30ed3517c2244d1330e39467b95f067a33bd + with: + oauth-client-id: ${{ secrets.TAILSCALE_CLIENT_ID }} + oauth-secret: ${{ secrets.TAILSCALE_SECRET }} + tags: tag:deploy-ci + hostname: Github-actions + version: ${{ vars.TAILSCALE_VERSION }} + + - name: Add secrets to config files + env: + DISCOURSE_SMTP_PASSWORD: ${{ secrets.DISCOURSE_SMTP_PASSWORD }} + DISCOURSE_DB_PASSWORD: ${{ secrets.DISCOURSE_DB_PASSWORD }} + DISCOURSE_MAXMIND_LICENSE_KEY: ${{ secrets.DISCOURSE_MAXMIND_LICENSE_KEY }} + DISCOURSE_S3_ENDPOINT: ${{ secrets.DISCOURSE_S3_ENDPOINT }} + DISCOURSE_S3_SECRET_ACCESS_KEY: ${{ secrets.DISCOURSE_S3_SECRET_ACCESS_KEY }} + DISCOURSE_S3_ACCESS_KEY_ID: ${{ secrets.DISCOURSE_S3_ACCESS_KEY_ID }} + run: | + sed -i "s|(DISCOURSE_SMTP_PASSWORD)|$DISCOURSE_SMTP_PASSWORD|g" $GITHUB_WORKSPACE/discourse/app.yml + sed -i "s|(DISCOURSE_DB_PASSWORD)|$DISCOURSE_DB_PASSWORD|g" $GITHUB_WORKSPACE/discourse/app.yml + sed -i "s|(DISCOURSE_MAXMIND_LICENSE_KEY)|$DISCOURSE_MAXMIND_LICENSE_KEY|g" $GITHUB_WORKSPACE/discourse/app.yml + sed -i "s|(DISCOURSE_S3_ENDPOINT)|$DISCOURSE_S3_ENDPOINT|g" $GITHUB_WORKSPACE/discourse/app.yml + sed -i "s|(DISCOURSE_S3_SECRET_ACCESS_KEY)|$DISCOURSE_S3_SECRET_ACCESS_KEY|g" $GITHUB_WORKSPACE/discourse/app.yml + sed -i "s|(DISCOURSE_S3_ACCESS_KEY_ID)|$DISCOURSE_S3_ACCESS_KEY_ID|g" $GITHUB_WORKSPACE/discourse/app.yml + sed -i "s|(DISCOURSE_DB_PASSWORD)|$DISCOURSE_DB_PASSWORD|g" $GITHUB_WORKSPACE/discourse/db.yml + + - name: Start Deployment + uses: FarisZR/Tailscale-ssh-deploy@main + with: + remote_host: ${{ secrets.server_address }} + directory: discourse + args: -p caddy up -d --remove-orphans + post_upload_command: /home/aosus/discourse/launcher rebuild db + remote_destination: /home/aosus/discourse/containers \ No newline at end of file diff --git a/.github/workflows/discourse.yml b/.github/workflows/discourse.yml new file mode 100644 index 0000000..043d7ac --- /dev/null +++ b/.github/workflows/discourse.yml @@ -0,0 +1,53 @@ +name: deploy-discourse + +on: + push: + paths: + - '.github/workflows/discourse.yml' + - 'discourse/app.yml' + branches: [main] + workflow_dispatch: + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - name: checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Tailscale + uses: tailscale/github-action@7a0b30ed3517c2244d1330e39467b95f067a33bd + with: + oauth-client-id: ${{ secrets.TAILSCALE_CLIENT_ID }} + oauth-secret: ${{ secrets.TAILSCALE_SECRET }} + tags: tag:deploy-ci + hostname: Github-actions + version: ${{ vars.TAILSCALE_VERSION }} + + - name: Add secrets to config files + env: + DISCOURSE_SMTP_PASSWORD: ${{ secrets.DISCOURSE_SMTP_PASSWORD }} + DISCOURSE_DB_PASSWORD: ${{ secrets.DISCOURSE_DB_PASSWORD }} + DISCOURSE_MAXMIND_LICENSE_KEY: ${{ secrets.DISCOURSE_MAXMIND_LICENSE_KEY }} + DISCOURSE_S3_ENDPOINT: ${{ secrets.DISCOURSE_S3_ENDPOINT }} + DISCOURSE_S3_SECRET_ACCESS_KEY: ${{ secrets.DISCOURSE_S3_SECRET_ACCESS_KEY }} + DISCOURSE_S3_ACCESS_KEY_ID: ${{ secrets.DISCOURSE_S3_ACCESS_KEY_ID }} + run: | + sed -i "s|(DISCOURSE_SMTP_PASSWORD)|$DISCOURSE_SMTP_PASSWORD|g" $GITHUB_WORKSPACE/discourse/app.yml + sed -i "s|(DISCOURSE_DB_PASSWORD)|$DISCOURSE_DB_PASSWORD|g" $GITHUB_WORKSPACE/discourse/app.yml + sed -i "s|(DISCOURSE_MAXMIND_LICENSE_KEY)|$DISCOURSE_MAXMIND_LICENSE_KEY|g" $GITHUB_WORKSPACE/discourse/app.yml + sed -i "s|(DISCOURSE_S3_ENDPOINT)|$DISCOURSE_S3_ENDPOINT|g" $GITHUB_WORKSPACE/discourse/app.yml + sed -i "s|(DISCOURSE_S3_SECRET_ACCESS_KEY)|$DISCOURSE_S3_SECRET_ACCESS_KEY|g" $GITHUB_WORKSPACE/discourse/app.yml + sed -i "s|(DISCOURSE_S3_ACCESS_KEY_ID)|$DISCOURSE_S3_ACCESS_KEY_ID|g" $GITHUB_WORKSPACE/discourse/app.yml + sed -i "s|(DISCOURSE_DB_PASSWORD)|$DISCOURSE_DB_PASSWORD|g" $GITHUB_WORKSPACE/discourse/db.yml + + - name: Start Deployment + uses: FarisZR/Tailscale-ssh-deploy@main + with: + remote_host: ${{ secrets.server_address }} + directory: discourse + args: -p caddy up -d --remove-orphans + post_upload_command: /home/aosus/discourse/launcher rebuild app + remote_destination: /home/aosus/discourse/containers \ No newline at end of file diff --git a/caddy/configs/discourse.caddyfile b/caddy/configs/discourse.caddyfile new file mode 100644 index 0000000..59261d4 --- /dev/null +++ b/caddy/configs/discourse.caddyfile @@ -0,0 +1,14 @@ +discourse.aosus.org { + header { + Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" + } + handle_errors { + # handle_errors is only triggerd on erros from Caddy and not the proxy, that's why we don't specifiy any errors here. + rewrite * /proxy_error_page.html + file_server { + root /srv/ + } + } + reverse_proxy app:80 + encode zstd gzip +} diff --git a/discourse/app.yml b/discourse/app.yml new file mode 100644 index 0000000..a8e390f --- /dev/null +++ b/discourse/app.yml @@ -0,0 +1,155 @@ +# IMPORTANT: SET A SECRET PASSWORD in Postgres for the Discourse User +# TODO: change SOME_SECRET in this template + +templates: + - "templates/web.template.yml" + - "templates/web.ratelimited.template.yml" + - "templates/web.ipv6.template.yml" +## Uncomment these two lines if you wish to add Lets Encrypt (https) + #- "templates/web.ssl.template.yml" + #- "templates/web.letsencrypt.ssl.template.yml" + +## which TCP/IP ports should this container expose? +## If you want Discourse to share a port with another webserver like Apache or nginx, +## see https://meta.discourse.org/t/17247 for details +expose: + # - "8000:80" # http + # - "443:443" # https + +# Use 'links' key to link containers together, aka use Docker --link flag. +# links: + # - link: + # name: data + # alias: data + # - link: + # name: nginx + # alias: nginx + +# any extra arguments for Docker? +docker_args: + - '--network discourse' + # - '--label com.centurylinklabs.watchtower.enable=false' +params: + ## Which Git revision should this container use? (default: tests-passed) + #version: stable + +env: + LC_ALL: en_US.UTF-8 + LANG: en_US.UTF-8 + LANGUAGE: en_US.UTF-8 + DISCOURSE_DEFAULT_LOCALE: ar + + ## How many concurrent web requests are supported? Depends on memory and CPU cores. + ## will be set automatically by bootstrap based on detected CPUs, or you can override + UNICORN_WORKERS: 12 + + ## TODO: The domain name this Discourse instance will respond to + DISCOURSE_HOSTNAME: 'discourse.aosus.org' + + ## Uncomment if you want the container to be started with the same + ## hostname (-h option) as specified above (default "$hostname-$config") + #DOCKER_USE_HOSTNAME: true + + ## TODO: List of comma delimited emails that will be made admin and developer + ## on initial signup example 'user1@example.com,user2@example.com' + DISCOURSE_DEVELOPER_EMAILS: 'acc@aosus.org' + + ## TODO: The SMTP mail server used to validate new accounts and send notifications + # SMTP ADDRESS, username, and password are required + # WARNING the char '#' in SMTP password can cause problems! + # DISCOURSE_SMTP_ADDRESS: smtp.email.me-jeddah-1.oci.oraclecloud.com + # DISCOURSE_SMTP_PORT: 587 + # DISCOURSE_SMTP_USER_NAME: "ocid1.user.oc1..aaaaaaaawotk2inxqyojzscjifrty4d27mjxuoxq3wwhnl5s76xubp7g4rja@ocid1.tenancy.oc1..aaaaaaaamsnkmv7r7ge76cjtcyusdpfyl77loyjfw7epb6rkmqdyz5vlknkq.rf.com" + # DISCOURSE_SMTP_PASSWORD: "(Xxk$786>Yj;vZA(xeNP" + # DISCOURSE_SMTP_ENABLE_START_TLS: true # (optional, default true) + # DISCOURSE_SMTP_DOMAIN: discourse.aosus.org # (required by some providers) + # DISCOURSE_NOTIFICATION_EMAIL: no-reply@discourse.aosus.org # (address to send notifications from) + + DISCOURSE_SMTP_ADDRESS: mail.cups-1.aosus.org + DISCOURSE_SMTP_PORT: 587 + DISCOURSE_SMTP_USER_NAME: "system@discourse.aosus.org" + DISCOURSE_SMTP_PASSWORD: "(DISCOURSE_SMTP_PASSWORD)" + DISCOURSE_SMTP_ENABLE_START_TLS: true # (optional, default true) + DISCOURSE_SMTP_DOMAIN: discourse.aosus.org # (required by some providers) + DISCOURSE_NOTIFICATION_EMAIL: system@discourse.aosus.org # (address to send notifications from) + ## If you added the Lets Encrypt template, uncomment below to get a free SSL certificate + #LETSENCRYPT_ACCOUNT_EMAIL: me@example.com + + ## TODO: configure connectivity to the databases + DISCOURSE_DB_SOCKET: '5432' + DISCOURSE_DB_USERNAME: discourse + DISCOURSE_DB_PASSWORD: (DISCOURSE_DB_PASSWORD) + DISCOURSE_DB_HOST: db + DISCOURSE_REDIS_HOST: db + + ## The http or https CDN address for this Discourse instance (configured to pull) + ## see https://meta.discourse.org/t/14857 for details + #DISCOURSE_CDN_URL: https://discourse-cdn.example.com + + ## The maxmind geolocation IP address key for IP address lookup + ## see https://meta.discourse.org/t/-/137387/23 for details + DISCOURSE_MAXMIND_LICENSE_KEY: (DISCOURSE_MAXMIND_LICENSE_KEY) + + DISCOURSE_USE_S3: true + DISCOURSE_S3_REGION: "us-east-1" + DISCOURSE_S3_INSTALL_CORS_RULE: true + #DISCOURSE_S3_CONFIGURE_TOMBSTONE_POLICY: false + DISCOURSE_S3_ENDPOINT: (DISCOURSE_S3_ENDPOINT) + DISCOURSE_S3_ACCESS_KEY_ID: (DISCOURSE_S3_ACCESS_KEY_ID) + DISCOURSE_S3_SECRET_ACCESS_KEY: (DISCOURSE_S3_SECRET_ACCESS_KEY) + DISCOURSE_S3_CDN_URL: https://cdn-cf-discourse.aosus.org + DISCOURSE_S3_BUCKET: discourse-cdn + DISCOURSE_S3_BACKUP_BUCKET: discourse-backups + DISCOURSE_BACKUP_LOCATION: s3 + + +volumes: + - volume: + host: /home/aosus/discourse-data/app + guest: /shared + - volume: + host: /home/aosus/discourse-data/app/log/var-log + guest: /var/log + +## Plugins go here +## see https://meta.discourse.org/t/19157 for details +hooks: + # required for S3 + after_assets_precompile: + - exec: + cd: $home + cmd: + - sudo -E -u discourse bundle exec rake s3:upload_assets + - sudo -E -u discourse bundle exec rake s3:expire_missing_assets + after_code: + - exec: + cd: $home/plugins + cmd: + - git clone https://github.com/discourse/docker_manager.git + - git clone https://github.com/discourse/discourse-reactions + - git clone https://github.com/discourse/discourse-category-experts + - git clone https://github.com/discourse/discourse-solved + #- git clone https://github.com/davidtaylorhq/discourse-telegram-notifications + - git clone https://github.com/discourse/discourse-chat-integration + - git clone https://github.com/discourse/discourse-math + - git clone https://github.com/discourse/discourse-linkedin-auth # Linkedin Auth + - git clone https://github.com/discourse/discourse-gamification # Gamification + - git clone https://github.com/discourse/discourse-yearly-review # yearly review + - git clone https://github.com/paviliondev/discourse-legal-tools # GDPR data export and so on + # - git clone https://github.com/discourse/discourse-google-one-tap # Google one tap login + +## Remember, this is YAML syntax - you can only have one block with a name +run: + - exec: echo "Beginning of custom commands" + + ## If you want to configure password login for root, uncomment and change: + ## Use only one of the following lines: + #- exec: /usr/sbin/usermod -p 'PASSWORD_HASH' root + #- exec: /usr/sbin/usermod -p "$(mkpasswd -m sha-256 'RAW_PASSWORD')" root + + ## If you want to authorized additional users, uncomment and change: + #- exec: ssh-import-id username + #- exec: ssh-import-id anotherusername + + - exec: echo "End of custom commands" + - exec: awk -F\# '{print $1;}' ~/.ssh/authorized_keys | awk 'BEGIN { print "Authorized SSH keys for this container:"; } NF>=2 {print $NF;}' \ No newline at end of file diff --git a/discourse/db.yml b/discourse/db.yml new file mode 100644 index 0000000..0738c9c --- /dev/null +++ b/discourse/db.yml @@ -0,0 +1,45 @@ +# A container for all things Data, be sure to set a secret password for +# discourse account, SOME_SECRET is just an example +# + +templates: + - "templates/postgres.template.yml" + - "templates/redis.template.yml" + +# any extra arguments for Docker? +docker_args: + - '--network discourse' + +params: + db_default_text_search_config: "pg_catalog.arabic" + + ## Set db_shared_buffers to a max of 25% of the total memory. + ## will be set automatically by bootstrap based on detected RAM, or you can override + #db_shared_buffers: "8GB" + + ## can improve sorting performance, but adds memory usage per-connection + db_work_mem: "80MB" + +env: + # ensure locale exists in container, you may need to install it + LC_ALL: en_US.UTF-8 + LANG: en_US.UTF-8 + LANGUAGE: en_US.UTF-8 + +volumes: + - volume: + host: /home/aosus/discourse-data/postgresql + guest: /shared + - volume: + host: /home/aosus/discourse-data/postgresql/log/var-log + guest: /var/log + +# TODO: SOME_SECRET to a password for the discourse user +hooks: + after_postgres: + - exec: + stdin: | + alter user discourse with password '(DISCOURSE_DB_PASSWORD)'; + cmd: su - postgres -c 'psql discourse' + + raise_on_fail: false \ No newline at end of file