# Sources used for this configuration: # - https://github.com/penpot/penpot/blob/2.1.0/docker/images/docker-compose.yaml # - https://raw.githubusercontent.com/penpot/penpot/2.1.0/docker/images/docker-compose.yaml # - https://help.penpot.app/technical-guide/configuration/ # - https://medium.com/@social.iodols/managing-docker-containers-in-nixos-fbda0f666dd1 # - https://madison-technologies.com/take-your-nixos-container-config-and-shove-it/ { config, pkgs, ... }: let # Flags for both frontend and backend. # https://help.penpot.app/technical-guide/configuration/#common # https://github.com/penpot/penpot/commit/ea7ad2aaa096f8d190d740f693f22f3ed1f05088 commonPenpotFlags = "disable-registration enable-oidc-registration disable-login-with-password enable-login-with-oidc"; penpotVersion = "2.1.3"; in { virtualisation.docker.enable = true; virtualisation.oci-containers = { backend = "docker"; containers = { "penpot-frontend" = { autoStart = true; image = "docker.io/penpotapp/frontend:${penpotVersion}"; extraOptions = [ "--network=penpot" ]; ports = [ "9001:80" ]; volumes = [ "penpot_assets:/opt/data/assets" ]; dependsOn = [ "penpot-backend" "penpot-exporter" ]; environment = { # https://help.penpot.app/technical-guide/configuration/#frontend # https://github.com/penpot/penpot/blob/develop/docker/images/docker-compose.yaml#L78 PENPOT_FLAGS = "${commonPenpotFlags} disable-onboarding"; }; }; "penpot-backend" = { autoStart = true; image = "docker.io/penpotapp/backend:${penpotVersion}"; extraOptions = [ "--network=penpot" ]; volumes = [ "penpot_assets:/opt/data/assets" ]; dependsOn = [ "penpot-postgres" "penpot-redis" ]; environment = { # https://help.penpot.app/technical-guide/configuration/#backend # https://github.com/penpot/penpot/blob/develop/docker/images/docker-compose.yaml#L112 PENPOT_FLAGS = "${commonPenpotFlags} enable-smtp"; # PENPOT_SECRET_KEY st via environmentFile. PENPOT_TELEMETRY_ENABLED = "false"; # OpenID Connect configuration. # https://help.penpot.app/technical-guide/configuration/#openid-connect PENPOT_OIDC_CLIENT_ID = "penpot"; PENPOT_OIDC_BASE_URI = "https://id.hamburg.ccc.de/realms/ccchh/"; # PENPOT_OIDC_CLIENT_SECRET set via environmentFile. PENPOT_OIDC_ROLES = "user"; PENPOT_OIDC_ROLES_ATTR = "roles"; # Database configuration. # https://help.penpot.app/technical-guide/configuration/#database PENPOT_DATABASE_USERNAME = "penpot"; # PENPOT_DATABASE_PASSWORD set via environmentFile. PENPOT_DATABASE_URI = "postgresql://penpot-postgres/penpot"; # Email configuration. # https://help.penpot.app/technical-guide/configuration/#email-(smtp) PENPOT_SMTP_HOST = "cow.hamburg.ccc.de"; PENPOT_SMTP_PORT = "465"; PENPOT_SMTP_USERNAME = "no-reply@design.hamburg.ccc.de"; # PENPOT_SMTP_PASSWORD set via environmentFile. PENPOT_SMTP_SSL = "true"; PENPOT_SMTP_DEFAULT_REPLY_TO = "Penpot "; PENPOT_SMTP_DEFAULT_FROM = "Penpot "; # Storage # https://help.penpot.app/technical-guide/configuration/#storage PENPOT_ASSETS_STORAGE_BACKEND = "assets-fs"; PENPOT_STORAGE_ASSETS_FS_DIRECTORY = "/opt/data/assets"; # Redis # https://help.penpot.app/technical-guide/configuration/#redis PENPOT_REDIS_URI = "redis://penpot-redis/0"; PENPOT_PUBLIC_URI = "https://design.hamburg.ccc.de"; }; environmentFiles = [ "/run/secrets/penpot_backend_environment_file" ]; }; "penpot-exporter" = { autoStart = true; image = "docker.io/penpotapp/exporter:${penpotVersion}"; extraOptions = [ "--network=penpot" ]; environment = { # https://help.penpot.app/technical-guide/configuration/#exporter # https://github.com/penpot/penpot/blob/develop/docker/images/docker-compose.yaml#L221 PENPOT_PUBLIC_URI = "http://penpot-frontend"; PENPOT_REDIS_URI = "redis://penpot-redis/0"; }; }; "penpot-postgres" = { autoStart = true; image = "docker.io/library/postgres:15"; extraOptions = [ "--stop-signal=SIGINT" "--network=penpot" ]; volumes = [ "penpot_postgres_v15:/var/lib/postgresql/data" ]; environment = { # https://github.com/penpot/penpot/blob/develop/docker/images/docker-compose.yaml#L240 POSTGRES_INITDB_ARGS = "--data-checksums"; POSTGRES_DB = "penpot"; POSTGRES_USER = "penpot"; # POSTGRES_PASSWORD set via environmentFile. }; environmentFiles = [ "/run/secrets/penpot_postgres_environment_file" ]; }; "penpot-redis" = { autoStart = true; image = "docker.io/library/redis:7"; extraOptions = [ "--network=penpot" ]; }; }; }; # Docker networks. systemd.services."docker-network-penpot" = { serviceConfig = { Type = "oneshot"; RemainAfterExit = true; ExecStop = "${pkgs.docker}/bin/docker network rm -f penpot"; }; script = "${pkgs.docker}/bin/docker network inspect penpot || ${pkgs.docker}/bin/docker network create penpot"; requiredBy = [ "docker-penpot-frontend.service" "docker-penpot-backend.service" "docker-penpot-exporter.service" "docker-penpot-postgres.service" "docker-penpot-redis.service" ]; before = [ "docker-penpot-frontend.service" "docker-penpot-backend.service" "docker-penpot-exporter.service" "docker-penpot-postgres.service" "docker-penpot-redis.service" ]; }; # Pull docker images prior to starting container services, so that a container # service isn't considered up, if it actually is still just pulling the # relevant image. systemd.services."docker-images-penpot" = { serviceConfig = { Type = "oneshot"; RemainAfterExit = true; }; script = '' ${pkgs.docker}/bin/docker pull ${config.virtualisation.oci-containers.containers."penpot-frontend".image} ${pkgs.docker}/bin/docker pull ${config.virtualisation.oci-containers.containers."penpot-backend".image} ${pkgs.docker}/bin/docker pull ${config.virtualisation.oci-containers.containers."penpot-exporter".image} ${pkgs.docker}/bin/docker pull ${config.virtualisation.oci-containers.containers."penpot-postgres".image} ${pkgs.docker}/bin/docker pull ${config.virtualisation.oci-containers.containers."penpot-redis".image} ''; requiredBy = [ "docker-penpot-frontend.service" "docker-penpot-backend.service" "docker-penpot-exporter.service" "docker-penpot-postgres.service" "docker-penpot-redis.service" ]; before = [ "docker-penpot-frontend.service" "docker-penpot-backend.service" "docker-penpot-exporter.service" "docker-penpot-postgres.service" "docker-penpot-redis.service" ]; }; sops.secrets."penpot_backend_environment_file" = { mode = "0440"; owner = "root"; group = "root"; }; sops.secrets."penpot_postgres_environment_file" = { mode = "0440"; owner = "root"; group = "root"; }; }