diff --git a/roles/docker/defaults/main.yml b/roles/docker/defaults/main.yml index 922f670..1e6df97 100644 --- a/roles/docker/defaults/main.yml +++ b/roles/docker/defaults/main.yml @@ -3,6 +3,8 @@ volume_root_folder: "/docker-volumes" volume_website_folder: "{{ volume_root_folder }}/websites" +external_services_network_subnet: '172.28.0.0/16' + services: ### Internal services ### postfix: @@ -224,8 +226,12 @@ services: volume_folder: "{{ volume_root_folder }}/fedidk-nodebb" pre_deploy_tasks: true version: "4.0.4" + nginx_version: 1.27.4-alpine + redis_version: 7.4.2-alpine mongodb_version: 7-jammy allowed_sender_domain: true + nodebb_port_begin: 4567 + nodebb_processes: 8 ### Uptime monitoring ### uptime_kuma: diff --git a/roles/docker/files/vhost/fedi_dk_nodebb b/roles/docker/files/vhost/fedi_dk_nodebb new file mode 100644 index 0000000..cdb0141 --- /dev/null +++ b/roles/docker/files/vhost/fedi_dk_nodebb @@ -0,0 +1 @@ +client_max_body_size 50M; # default is 1M \ No newline at end of file diff --git a/roles/docker/tasks/pre_deploy/fedi_dk_nodebb.yml b/roles/docker/tasks/pre_deploy/fedi_dk_nodebb.yml index 1aad8a0..10a6ba1 100644 --- a/roles/docker/tasks/pre_deploy/fedi_dk_nodebb.yml +++ b/roles/docker/tasks/pre_deploy/fedi_dk_nodebb.yml @@ -1,5 +1,19 @@ # vim: ft=yaml.ansible --- +- name: Create subdirectory for NGINX config files + ansible.builtin.file: + path: "{{ services.fedi_dk_nodebb.volume_folder }}/nginx" + owner: root + mode: u=rwx,g=rx,o=rx + state: directory + +- name: Upload NGINX configs + ansible.builtin.template: + src: fedi_dk_nodebb/nginx/http.conf.j2 + dest: "{{ services.fedi_dk_nodebb.volume_folder }}/nginx/http.conf" + owner: root + mode: u=rw,g=r,o=r + - name: Create subfolder for uploads file: name: "{{ services.fedi_dk_nodebb.volume_folder }}/uploads" @@ -12,7 +26,7 @@ name: "{{ services.fedi_dk_nodebb.volume_folder }}/build" state: directory owner: '1001' - mode: u=rwx,go= + mode: u=rwx,g=rx,o=rx - name: Create subfolder for config file: @@ -48,3 +62,8 @@ dest: "{{ services.fedi_dk_nodebb.volume_folder }}/mongodb-user-init.js" owner: '999' mode: u=rw,go= + +- name: Upload vhost config for NodeBB domain + copy: + src: vhost/fedi_dk_nodebb + dest: "{{ services.nginx_proxy.volume_folder }}/vhost/{{ services.fedi_dk_nodebb.domain }}" diff --git a/roles/docker/tasks/services.yml b/roles/docker/tasks/services.yml index 2c7276f..fe00a4e 100644 --- a/roles/docker/tasks/services.yml +++ b/roles/docker/tasks/services.yml @@ -3,6 +3,9 @@ - name: Set up external services network docker_network: name: external_services + enable_ipv6: false + ipam_config: + - subnet: "{{ external_services_network_subnet }}" - name: Deploy all services include_tasks: diff --git a/roles/docker/templates/compose-files/fedi_dk_nodebb.yml.j2 b/roles/docker/templates/compose-files/fedi_dk_nodebb.yml.j2 index f74825f..c501d90 100644 --- a/roles/docker/templates/compose-files/fedi_dk_nodebb.yml.j2 +++ b/roles/docker/templates/compose-files/fedi_dk_nodebb.yml.j2 @@ -1,33 +1,66 @@ services: + nginx: + image: nginx:{{ services.fedi_dk_nodebb.nginx_version }} + restart: always + networks: + - default + - external_services + volumes: + - "./nginx:/etc/nginx/conf.d:ro" + - "./build:/usr/src/app/build:ro" + environment: + VIRTUAL_HOST: {{ services.fedi_dk_nodebb.domain }} + VIRTUAL_PORT: 80 + LETSENCRYPT_HOST: {{ services.fedi_dk_nodebb.domain }} + LETSENCRYPT_EMAIL: {{ letsencrypt_email }} + depends_on: + - app + + redis: + image: redis:{{ services.fedi_dk_nodebb.redis_version }} + restart: unless-stopped + tmpfs: + - /var/lib/redis + healthcheck: + test: ["CMD", "redis-cli", "ping"] + interval: 10s + timeout: 3s + retries: 5 + mongodb: image: mongo:{{ services.fedi_dk_nodebb.mongodb_version }} restart: always volumes: - - ./mongodb:/data/db:rw - - ./mongodb-user-init.js:/docker-entrypoint-initdb.d/user-init.js:ro + - "./mongodb:/data/db:rw" + - "./mongodb-user-init.js:/docker-entrypoint-initdb.d/user-init.js:ro" environment: MONGO_INITDB_ROOT_USERNAME: nodebb MONGO_INITDB_ROOT_PASSWORD: {{ fedi_dk_nodebb_secrets.mongodb_password }} + healthcheck: + test: ["CMD", "mongosh", "--quiet", "127.0.0.1/test", "--eval", "'quit(db.runCommand({ ping: 1 }).ok ? 0 : 2)'"] + interval: 10s + timeout: 10s + retries: 5 + start_period: 40s app: image: ghcr.io/nodebb/nodebb:{{ services.fedi_dk_nodebb.version }} restart: always networks: - - default - - postfix - - external_services + default: + aliases: + - app.nodebb + postfix: volumes: - - ./build:/usr/src/app/build:rw - - ./uploads:/usr/src/app/public/uploads:rw - - ./config:/opt/config:rw - - ./setup.json:/usr/src/app/setup.json:ro - environment: - VIRTUAL_HOST: {{ services.fedi_dk_nodebb.domain }} - VIRTUAL_PORT: 4567 - LETSENCRYPT_HOST: {{ services.fedi_dk_nodebb.domain }} - LETSENCRYPT_EMAIL: {{ letsencrypt_email }} + - "./build:/usr/src/app/build:rw" + - "./uploads:/usr/src/app/public/uploads:rw" + - "./config:/opt/config:rw" + - "./setup.json:/usr/src/app/setup.json:ro" depends_on: - - mongodb + redis: + condition: service_healthy + mongodb: + condition: service_healthy networks: postfix: diff --git a/roles/docker/templates/fedi_dk_nodebb/config.json.j2 b/roles/docker/templates/fedi_dk_nodebb/config.json.j2 index 978029b..f49119f 100644 --- a/roles/docker/templates/fedi_dk_nodebb/config.json.j2 +++ b/roles/docker/templates/fedi_dk_nodebb/config.json.j2 @@ -1,8 +1,10 @@ { - "url": "https://forum.data.coop", + "url": "https://{{ services.fedi_dk_nodebb.domain }}", "secret": "{{ fedi_dk_nodebb_secrets.secret_value }}", "database": "mongo", - "port": "4567", + "port": [{% for port in range(services.fedi_dk_nodebb.nodebb_port_begin, + services.fedi_dk_nodebb.nodebb_port_begin + services.fedi_dk_nodebb.nodebb_processes) + %}"{{ port }}"{% if not loop.last %}, {% endif %}{% endfor %}], "mongo": { "host": "mongodb", "port": "27017", @@ -10,5 +12,10 @@ "password": "{{ fedi_dk_nodebb_secrets.mongodb_password }}", "database": "admin", "uri": "" + }, + "redis": { + "host": "redis", + "port": "6379", + "database": 0 } -} \ No newline at end of file +} diff --git a/roles/docker/templates/fedi_dk_nodebb/nginx/http.conf.j2 b/roles/docker/templates/fedi_dk_nodebb/nginx/http.conf.j2 new file mode 100644 index 0000000..6940550 --- /dev/null +++ b/roles/docker/templates/fedi_dk_nodebb/nginx/http.conf.j2 @@ -0,0 +1,54 @@ +resolver 127.0.0.11 valid=30s ipv6=off; + +set_real_ip_from {{ external_services_network_subnet }}; +real_ip_header X-Forwarded-For; +real_ip_recursive on; + +map $http_upgrade $connection_upgrade { + default upgrade; + '' close; +} + +upstream workers { + ip_hash; +{% for port in range(services.fedi_dk_nodebb.nodebb_port_begin, + services.fedi_dk_nodebb.nodebb_port_begin + services.fedi_dk_nodebb.nodebb_processes) %} + server app.nodebb:{{ port }}; +{% endfor %} +} + +server { + server_name {{ services.fedi_dk_nodebb.domain }}; + listen 80; + + set $upstream http://workers; + + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Host $http_host; + proxy_set_header X-NginX-Proxy true; + proxy_redirect off; + + # Socket.io Support + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + + gzip on; + gzip_min_length 1000; + gzip_proxied off; + gzip_types text/plain application/xml text/javascript application/javascript application/x-javascript text/css application/json; + + location @nodebb { + proxy_pass $upstream; + } + + location ~ ^/assets/(.*) { + root /usr/src/app; + try_files /build/public/$1 @nodebb; + } + + location / { + proxy_pass $upstream; + } +}