diff --git a/proxy_resources/etc/wireguard/wg0.conf b/proxy_resources/etc/wireguard/wg0.conf index 9f0ba46..ade6b6f 100755 --- a/proxy_resources/etc/wireguard/wg0.conf +++ b/proxy_resources/etc/wireguard/wg0.conf @@ -61,6 +61,12 @@ PublicKey = {{ technitium_service_pubkey }} AllowedIPs = 10.0.0.10/32 PersistentKeepalive = 25 +# Penpot Service +[Peer] +PublicKey = {{ penpot_service_pubkey }} +AllowedIPs = 10.0.0.11/32 +PersistentKeepalive = 25 + # Connection to backend server for nagios [Peer] PublicKey = {{ nagios_backend_pubkey }} diff --git a/services/service_penpot/ansible.cfg b/services/service_penpot/ansible.cfg new file mode 100644 index 0000000..b46bfad --- /dev/null +++ b/services/service_penpot/ansible.cfg @@ -0,0 +1,6 @@ +[defaults] +inventory = ../../hosts + +[privilege_escalation] +become_method=doas +become_ask_pass=True diff --git a/services/service_penpot/deploy-service.yml b/services/service_penpot/deploy-service.yml new file mode 100644 index 0000000..c10d906 --- /dev/null +++ b/services/service_penpot/deploy-service.yml @@ -0,0 +1,26 @@ +- hosts: localhost + become: 'yes' + vars: + ansible_become_method: doas + tasks: + - name: Create necessary directories + ansible.builtin.file: + path: "{{ item }}" + owner: service_penpot + group: service_penpot + state: directory + loop: + - "{{ services_directory }}/service_penpot/penpot" + + - name: Copy docker compose config and other git files + ansible.builtin.template: + src: "{{ item }}" + dest: "{{ services_directory }}/service_penpot/{{ item }}" + owner: service_penpot + group: service_penpot + loop: + - docker-compose.yml + + - name: Debug Finish message + debug: + msg: Ansible playbook has finished! diff --git a/services/service_penpot/docker-compose.yml b/services/service_penpot/docker-compose.yml new file mode 100644 index 0000000..c640efb --- /dev/null +++ b/services/service_penpot/docker-compose.yml @@ -0,0 +1,270 @@ +networks: + penpot: + +services: + + # Gluetun is used to connect container to VPN + penpot-gluetun: + image: qmcgaw/gluetun + cap_add: + - NET_ADMIN + environment: + - VPN_SERVICE_PROVIDER=custom + - VPN_TYPE=wireguard + - VPN_ENDPOINT_IP={{ proxy_server_ip }} + - VPN_ENDPOINT_PORT={{ proxy_server_vpn_port }} + - WIREGUARD_PUBLIC_KEY={{ vpn_server_pubkey }} + - WIREGUARD_PRIVATE_KEY={{ penpot_service_privkey }} + - WIREGUARD_ADDRESSES=10.0.0.11/32 + - FIREWALL_VPN_INPUT_PORTS=9001 + ports: + - "9001:80" + networks: + penpot: + deploy: + resources: + limits: + cpus: '0.10' + memory: 512M + + penpot-frontend: + network_mode: "service:penpot-gluetun" + image: "penpotapp/frontend:latest" + restart: always + + volumes: + - ./penpot_assets:/opt/data/assets + + depends_on: + - penpot-backend + - penpot-exporter + + labels: + #- "traefik.enable=true" + + ## HTTP: example of labels for the case where penpot will be exposed to the + ## internet with only HTTP (without HTTPS) using traefik. + + # - "traefik.http.routers.penpot-http.entrypoints=web" + # - "traefik.http.routers.penpot-http.rule=Host(``)" + # - "traefik.http.services.penpot-http.loadbalancer.server.port=80" + + ## HTTPS: example of labels for the case where penpot will be exposed to the + ## internet with HTTPS using traefik. + + # - "traefik.http.middlewares.http-redirect.redirectscheme.scheme=https" + # - "traefik.http.middlewares.http-redirect.redirectscheme.permanent=true" + # - "traefik.http.routers.penpot-http.entrypoints=web" + # - "traefik.http.routers.penpot-http.rule=Host(``)" + # - "traefik.http.routers.penpot-http.middlewares=http-redirect" + # - "traefik.http.routers.penpot-https.entrypoints=websecure" + # - "traefik.http.routers.penpot-https.rule=Host(``)" + # - "traefik.http.services.penpot-https.loadbalancer.server.port=80" + # - "traefik.http.routers.penpot-https.tls=true" + # - "traefik.http.routers.penpot-https.tls.certresolver=letsencrypt" + + ## Configuration envronment variables for the frontend container. In this case, the + ## container only needs the `PENPOT_FLAGS`. This environment variable is shared with + ## other services, but not all flags are relevant to all services. + + environment: + ## Relevant flags for frontend: + ## - demo-users + ## - login-with-github + ## - login-with-gitlab + ## - login-with-google + ## - login-with-ldap + ## - login-with-oidc + ## - login-with-password + ## - registration + ## - webhooks + ## + ## You can read more about all available flags on: + ## https://help.penpot.app/technical-guide/configuration/#advanced-configuration + + - PENPOT_FLAGS=enable-registration enable-login-with-password + + penpot-backend: + image: "penpotapp/backend:latest" + restart: always + + volumes: + - ./penpot_assets:/opt/data/assets + + depends_on: + - penpot-postgres + - penpot-redis + + networks: + penpot: + + ## Configuration envronment variables for the backend + ## container. + + environment: + + ## Relevant flags for backend: + ## - demo-users + ## - email-verification + ## - log-emails + ## - log-invitation-tokens + ## - login-with-github + ## - login-with-gitlab + ## - login-with-google + ## - login-with-ldap + ## - login-with-oidc + ## - login-with-password + ## - registration + ## - secure-session-cookies + ## - smtp + ## - smtp-debug + ## - telemetry + ## - webhooks + ## - prepl-server + ## + ## You can read more about all available flags and other + ## environment variables for the backend here: + ## https://help.penpot.app/technical-guide/configuration/#advanced-configuration + + - PENPOT_FLAGS=enable-registration enable-login-with-password disable-email-verification enable-smtp enable-prepl-server + + ## Penpot SECRET KEY. It serves as a master key from which other keys for subsystems + ## (eg http sessions, or invitations) are derived. + ## + ## If you leave it commented, all created sessions and invitations will + ## become invalid on container restart. + ## + ## If you going to uncomment this, we recommend to use a trully randomly generated + ## 512 bits base64 encoded string here. You can generate one with: + ## + ## python3 -c "import secrets; print(secrets.token_urlsafe(64))" + + # - PENPOT_SECRET_KEY=my-insecure-key + + ## The PREPL host. Mainly used for external programatic access to penpot backend + ## (example: admin). By default it will listen on `localhost` but if you are going to use + ## the `admin`, you will need to uncomment this and set the host to `0.0.0.0`. + + # - PENPOT_PREPL_HOST=0.0.0.0 + + ## Public URI. If you are going to expose this instance to the internet and use it + ## under a different domain than 'localhost', you will need to adjust it to the final + ## domain. + ## + ## Consider using traefik and set the 'disable-secure-session-cookies' if you are + ## not going to serve penpot under HTTPS. + + - PENPOT_PUBLIC_URI=http://localhost:9001 + + ## Database connection parameters. Don't touch them unless you are using custom + ## postgresql connection parameters. + + - PENPOT_DATABASE_URI=postgresql://11.3.0.24/penpot + - PENPOT_DATABASE_USERNAME=penpot + - PENPOT_DATABASE_PASSWORD={{ service_penpot_postgres_password }} + + ## Redis is used for the websockets notifications. Don't touch unless the redis + ## container has different parameters or different name. + + - PENPOT_REDIS_URI=redis://11.3.0.23/0 + + ## Default configuration for assets storage: using filesystem based with all files + ## stored in a docker volume. + + - PENPOT_ASSETS_STORAGE_BACKEND=assets-fs + - PENPOT_STORAGE_ASSETS_FS_DIRECTORY=/opt/data/assets + + ## Also can be configured to to use a S3 compatible storage + ## service like MiniIO. Look below for minio service setup. + + # - AWS_ACCESS_KEY_ID= + # - AWS_SECRET_ACCESS_KEY= + # - PENPOT_ASSETS_STORAGE_BACKEND=assets-s3 + # - PENPOT_STORAGE_ASSETS_S3_ENDPOINT=http://penpot-minio:9000 + # - PENPOT_STORAGE_ASSETS_S3_BUCKET= + + ## Telemetry. When enabled, a periodical process will send anonymous data about this + ## instance. Telemetry data will enable us to learn how the application is used, + ## based on real scenarios. If you want to help us, please leave it enabled. You can + ## audit what data we send with the code available on github. + + #- PENPOT_TELEMETRY_ENABLED=true + + ## Example SMTP/Email configuration. By default, emails are sent to the mailcatch + ## service, but for production usage it is recommended to setup a real SMTP + ## provider. Emails are used to confirm user registrations & invitations. Look below + ## how the mailcatch service is configured. + + - PENPOT_SMTP_DEFAULT_FROM=no-reply@example.com + - PENPOT_SMTP_DEFAULT_REPLY_TO=no-reply@example.com + - PENPOT_SMTP_HOST=11.3.0.22 + - PENPOT_SMTP_PORT=1025 + - PENPOT_SMTP_USERNAME= + - PENPOT_SMTP_PASSWORD= + - PENPOT_SMTP_TLS=false + - PENPOT_SMTP_SSL=false + + penpot-exporter: + image: "penpotapp/exporter:latest" + restart: always + networks: + - penpot + + environment: + # Don't touch it; this uses an internal docker network to + # communicate with the frontend. + - PENPOT_PUBLIC_URI=http://penpot-frontend + + ## Redis is used for the websockets notifications. + - PENPOT_REDIS_URI=redis://penpot-redis/0 + + penpot-postgres: + image: "postgres:15" + restart: always + stop_signal: SIGINT + + volumes: + - ./penpot_postgres_v15:/var/lib/postgresql/data + + networks: + penpot: + ipv4_address: 11.3.0.24 + + environment: + - POSTGRES_INITDB_ARGS=--data-checksums + - POSTGRES_DB=penpot + - POSTGRES_USER=penpot + - POSTGRES_PASSWORD={{ service_penpot_postgres_password }} + + penpot-redis: + image: redis:7 + restart: always + networks: + penpot: + ipv4_address: 11.3.0.23 + + ## A mailcatch service, used as temporal SMTP server. You can access via HTTP to the + ## port 1080 for read all emails the penpot platform has sent. Should be only used as a + ## temporal solution while no real SMTP provider is configured. + + penpot-mailcatch: + image: sj26/mailcatcher:latest + restart: always + expose: + - '1025' + ports: + - "1080:1080" + networks: + penpot: + ipv4_address: 11.3.0.22 + +networks: + penpot: + driver: bridge + driver_opts: + com.docker.network.bridge.name: penpot + # com.docker.network.driver.enable_ip_masquerade: 0 + ipam: + config: + - subnet: 11.3.0.0/16 + # gateway: 11.5.0.1 diff --git a/services/service_penpot/prox-deploy-service.yml b/services/service_penpot/prox-deploy-service.yml new file mode 100644 index 0000000..176e1e8 --- /dev/null +++ b/services/service_penpot/prox-deploy-service.yml @@ -0,0 +1,22 @@ +- hosts: + - "{{ proxy_server_hostname }}" + # - "{{ proxy_server_hostname }}"-defaultport + become: 'yes' + vars: + ansible_become_method: doas + tasks: + # Ensure NGinx site reverse proxy configuration is updated + - name: Ensure all NGinx site configurations are updated + template: + src: proxy_resources/etc/nginx/sites-available/penpot.domain + dest: "/etc/nginx/sites-available/penpot.{{ domain_name }}" + - name: Ensure NGinx site reverse proxy configuration is enabled + ansible.builtin.file: + src: "/etc/nginx/sites-available/penpot.{{ domain_name }}" + dest: "/etc/nginx/sites-enabled/penpot.{{ domain_name }}" + state: link + + - name: Debug Finish message + debug: + msg: Ansible playbook has finished! + diff --git a/services/service_penpot/proxy_resources/etc/nginx/sites-available/penpot.domain b/services/service_penpot/proxy_resources/etc/nginx/sites-available/penpot.domain new file mode 100755 index 0000000..ad123a8 --- /dev/null +++ b/services/service_penpot/proxy_resources/etc/nginx/sites-available/penpot.domain @@ -0,0 +1,49 @@ +# {{ ansible_managed }} + +# Penpot Proxy +server { + + server_name penpot.{{ domain_name }} www.penpot.{{ domain_name }}; + + location / { + proxy_pass http://10.0.0.11:80; + proxy_set_header X-Forwarded-For $remote_addr; + proxy_set_header Host $host; # so Invidious knows domain + proxy_http_version 1.1; # to keep alive + proxy_set_header Connection ""; # to keep alive + include proxy_params; + } + + client_max_body_size 512M; + + listen [::]:443 ssl ipv6only=on; # managed by Certbot + listen 443 ssl; # managed by Certbot + ssl_certificate /etc/letsencrypt/live/{{ domain_name }}/fullchain.pem; # managed by Certbot + ssl_certificate_key /etc/letsencrypt/live/{{ domain_name }}/privkey.pem; # managed by Certbot + include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot + ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot + + +} + +server { + if ($host = www.penpot.{{ domain_name }}) { + return 301 https://$host$request_uri; + } # managed by Certbot + + + if ($host = penpot.{{ domain_name }}) { + return 301 https://$host$request_uri; + } # managed by Certbot + + + listen 80; + listen [::]:80; + + server_name penpot.{{ domain_name }} www.penpot.{{ domain_name }}; + return 404; # managed by Certbot + + + + +} diff --git a/services/service_penpot/servicesecrets.example b/services/service_penpot/servicesecrets.example new file mode 100644 index 0000000..3ef25a8 --- /dev/null +++ b/services/service_penpot/servicesecrets.example @@ -0,0 +1,2 @@ +# Example service secrets for penpot docker service, to be encrypted with ansible vault and called servicesecrets.enc +service_penpot_postgres_password: password123