Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using docker secrets #272

Open
arthurpankiewicz opened this issue Sep 4, 2020 · 4 comments
Open

Using docker secrets #272

arthurpankiewicz opened this issue Sep 4, 2020 · 4 comments

Comments

@arthurpankiewicz
Copy link

arthurpankiewicz commented Sep 4, 2020

I was wondering if somebody could help me out here, I am trying to convert the docker-compose.yml from the repo to use docker secrets. However, it seems like certain services defined with a command fail when trying to access the secrets. Also, the zulip service gives an error when trying to access certain secrets in the entrypoint.sh

Relevant code snippets:

docker-compose

secrets:
  zulip_secrets.yaml:
    file: './secrets/zulip_secrets.yaml'

...

  zulip:
    build: .
    ...
    secrets:
      - zulip_secrets.yaml

zulip-secrets.yaml

secrets:
  rabbitmq:
    password: 'REPLACE_WITH_SECURE_RABBITMQ_PASSWORD'
  postgres:
    password: 'REPLACE_WITH_SECURE_POSTGRES_PASSWORD'
  memcached:
    password: 'REPLACE_WITH_SECURE_MEMCACHED_PASSWORD'
  redis:
    password: 'REPLACE_WITH_SECURE_REDIS_PASSWORD'
  secret:
    key: 'REPLACE_WITH_SECURE_SECRET_KEY'
  email:
    password: '123456789'

error:

zulip_1      | Waiting for database server to allow connections ...
zulip_1      | /sbin/entrypoint.sh: line 311: SECRETS_postgres_password: parameter null or not set
docker-zulip_zulip_1 exited with code 1

Thanks :)

@yasiruRathnayaka97
Copy link

@arthurpankiewicz you should have to name the password as "SECRETS_postgres_password:. Then it will work.

@amolvishwakarma
Copy link

amolvishwakarma commented Jan 20, 2022

You can also create a .env file and call in docker-compose.yml. Hope this will help you @arthurpankiewicz

.env

SECRETS_rabbitmq_password=abc
SECRETS_postgres_password=def
SECRETS_memcached_password=ghi
SECRETS_redis_password=jkl
SECRETS_secret_key=mno
SECRETS_email_password=xyz

docker-compose.yml

database:
    image: 'zulip/zulip-postgresql:10'
    container_name: "zulip_db"
    restart: unless-stopped
    env_file:
      - .env

@mnzaki
Copy link

mnzaki commented Oct 21, 2022

You also need to handle POSTGRES_PASSWORD in the database service, probably set it to the value of SECRETS_postgres_password

@so-rose
Copy link

so-rose commented Nov 24, 2022

+1 for native docker secrets support; it's bad practice to pass secrets via environment variable.

docker secrets mounts secrets to files located at /run/secrets/<secret_name> at runtime. Thus, adding docker secrets support is easy: Just allow for a *_FILE environment variable as an alternative.

For example, the zulip service would be defined with:

    secrets:
      - chat__postgres_pass
      - chat__memcached_pass
      - chat__rabbitmq_pass
      - chat__redis_pass
      - chat__secret_key
      - chat__email_pass
    
    environment:
      ....
      SECRETS_rabbitmq_password_FILE: /run/secrets/chat__rabbitmq_pass
      SECRETS_postgres_password_FILE: /run/secrets/chat__postgres_pass
      SECRETS_memcached_password_FILE: /run/secrets/chat__memcached_pass
      SECRETS_redis_password_FILE: /run/secrets/chat__redis_pass
      
      SECRETS_secret_key_FILE: /run/secrets/chat__secret_key
      SECRETS_email_password_FILE: /run/secrets/chat__email_pass

Right now, this doesn't work by itself. But there's a workaround by modifying command to export them after a cat:

    entrypoint: []
    command: [
      "/bin/sh", "-c",
      '
      export SECRETS_rabbitmq_password="$$(cat $$SECRETS_rabbitmq_password_FILE)" &&
      export SECRETS_postgres_password="$$(cat $$SECRETS_postgres_password_FILE)" &&
      export SECRETS_memcached_password="$$(cat $$SECRETS_memcached_password_FILE)" &&
      export SECRETS_redis_password="$$(cat $$SECRETS_redis_password_FILE)" &&
      export SECRETS_secret_key="$$(cat $$SECRETS_secret_key_FILE)" &&
      export SECRETS_email_password="$$(cat $$SECRETS_email_password_FILE)" &&
      /sbin/entrypoint.sh app:run
      '
    ]

Complete Working Stack w/Secrets

Here's a full working stack, compatible with Docker Swarm (using Traefik), which uses docker secrets. Notice the POSTGRES_PASSWORD_FILE, and the mods to the redis and memcached command.

version: "3.8"

services:
  db:
    image: "zulip/zulip-postgresql:14"
    
    secrets:
      - chat__postgres_pass
    
    environment:
      POSTGRES_DB: "zulip"
      POSTGRES_USER: "zulip"
      POSTGRES_PASSWORD_FILE: /run/secrets/chat__postgres_pass
    
    volumes:
      - /data/nest/runtime/chat/db:/var/lib/postgresql/data:rw
    
    networks:
      - private
  
  memcached:
    image: memcached:alpine
    command:
      - "sh"
      - "-euc"
      - |
        echo 'mech_list: plain' > "$$SASL_CONF_PATH"
        echo "zulip@$$HOSTNAME:$$(cat $$MEMCACHED_PASSWORD_FILE)" > "$$MEMCACHED_SASL_PWDB"
        echo "zulip@localhost:$$(cat $$MEMCACHED_PASSWORD_FILE)" >> "$$MEMCACHED_SASL_PWDB"
        exec memcached -S
    
    secrets:
      - chat__memcached_pass
    
    environment:
      SASL_CONF_PATH: "/home/memcache/memcached.conf"
      MEMCACHED_SASL_PWDB: "/home/memcache/memcached-sasl-db"
      MEMCACHED_PASSWORD_FILE: /run/secrets/chat__memcached_pass
    
    networks:
      - private
  
  rabbitmq:
    image: rabbitmq:3.7.7
    
    secrets:
      - chat__rabbitmq_pass
    
    environment:
      RABBITMQ_DEFAULT_USER: "zulip"
      RABBITMQ_DEFAULT_PASS_FILE: /run/secrets/chat__rabbitmq_pass
    
    volumes:
      - /data/nest/runtime/chat/rabbitmq:/var/lib/rabbitmq:rw
    
    networks:
      - private
  
  redis:
    image: redis:alpine
    
    secrets:
      - chat__redis_pass
    
    command:
      - "sh"
      - "-euc"
      - |
        echo "requirepass '$$(cat $$REDIS_PASS_FILE)'" > /etc/redis.conf
        exec redis-server /etc/redis.conf
    
    environment:
      REDIS_PASS_FILE: /run/secrets/chat__redis_pass
    
    volumes:
      - /data/nest/static/chat/redis:/data:rw
    
    networks:
      - private
  
  zulip:
    image: zulip/docker-zulip:5.7-0
    entrypoint: []
    command: [
      "/bin/sh", "-c",
      '
      export SECRETS_rabbitmq_password="$$(cat $$SECRETS_rabbitmq_password_FILE)" &&
      export SECRETS_postgres_password="$$(cat $$SECRETS_postgres_password_FILE)" &&
      export SECRETS_memcached_password="$$(cat $$SECRETS_memcached_password_FILE)" &&
      export SECRETS_redis_password="$$(cat $$SECRETS_redis_password_FILE)" &&
      export SECRETS_secret_key="$$(cat $$SECRETS_secret_key_FILE)" &&
      export SECRETS_email_password="$$(cat $$SECRETS_email_password_FILE)" &&
      /sbin/entrypoint.sh app:run
      '
    ]
    
    ulimits:
      nofile:
        soft: 1000000
        hard: 1048576
    
    secrets:
      - chat__postgres_pass
      - chat__memcached_pass
      - chat__rabbitmq_pass
      - chat__redis_pass
      - chat__secret_key
      - chat__email_pass
    
    environment:
      DB_HOST: "db"
      DB_HOST_PORT: "5432"
      DB_USER: "zulip"
      
      SETTING_MEMCACHED_LOCATION: "memcached:11211"
      SETTING_RABBITMQ_HOST: "rabbitmq"
      SETTING_REDIS_HOST: "redis"
      
      SECRETS_rabbitmq_password_FILE: /run/secrets/chat__rabbitmq_pass
      SECRETS_postgres_password_FILE: /run/secrets/chat__postgres_pass
      SECRETS_memcached_password_FILE: /run/secrets/chat__memcached_pass
      SECRETS_redis_password_FILE: /run/secrets/chat__redis_pass
      
      SECRETS_secret_key_FILE: /run/secrets/chat__secret_key
      SECRETS_email_password_FILE: /run/secrets/chat__email_pass
      
      DISABLE_HTTPS: "True"
      SSL_CERTIFICATE_GENERATION: "self-signed"
      SETTING_EXTERNAL_HOST: "chat.<redacted>"
      
      SETTING_ZULIP_ADMINISTRATOR: "zulip@<redacted>"
      SETTING_NOREPLY_EMAIL_ADDRESS: "zulip@<redacted>"
      SETTING_ADD_TOKENS_TO_NOREPLY_ADDRESS: "False"
      
      SETTING_EMAIL_HOST: "mx.<redacted>"
      SETTING_EMAIL_PORT: "465"
      SETTING_EMAIL_USE_SSL: "True"
      SETTING_EMAIL_HOST_USER: "zulip@<redacted>"
      
      
      
      ZULIP_AUTH_BACKENDS: "EmailAuthBackend"
      # Uncomment this when configuring the mobile push notifications service
      # SETTING_PUSH_NOTIFICATION_BOUNCER_URL: 'https://push.zulipchat.com'
    
    volumes:
      - /data/nest/static/chat/zulip:/data:rw
    
    deploy:
      labels:
        traefik.enable: "true"
        
        # Web Config
        traefik.http.routers.chat_zulip.rule: "Host(`chat.<redacted>`)"
        traefik.http.routers.chat_zulip.entrypoints: "web,websecure"
        traefik.http.routers.chat_zulip.service: "chat_zulip"
        traefik.http.services.chat_zulip.loadbalancer.server.port: 80
        
        traefik.http.routers.chat_zulip.tls: "true"
        traefik.http.routers.chat_zulip.tls.certresolver: "letsencrypt"

    
    networks:
      - mesh_public
      - private
    
secrets:
  chat__postgres_pass:
    external: true
  
  chat__memcached_pass:
    external: true
  
  chat__rabbitmq_pass:
    external: true
  
  chat__redis_pass:
    external: true
  
  chat__secret_key:
    external: true
  
  chat__email_pass:
    external: true

networks:
  mesh_public:
    external: true
  
  private:
    driver: overlay

Perhaps it'd be worth documenting this usage?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants