Enable HTTPS in dockerized Wallabag
From @Suncatcher on July 11, 2017 15:49
Issue details
How can I enable HTTPS on Docker installation on Wallabag? Didn't find any decent documentation on that. I see that Docker container uses nginx for Wallabag. Should I enable HTTPS in nginx config inside container?
Environment
- wallabag version that exhibits the issue: 2.2.2
- How did you install wallabag: Docker
- Last wallabag version that did not exhibit the issue: None
- php version: 7.0.16
- OS: AWS AMI Linux 2017.03
- type of hosting (shared or dedicated): AWS EC2 T2 Micro
- which storage system you choose at install (SQLite, MySQL/MariaDB or PostgreSQL): Postgre 9.6.2
Steps to reproduce/test case
Trying to enable HTTPS on Docker Wallabag
Copied from original issue: wallabag/wallabag#3275
From @Suncatcher on July 31, 2017 12:51
Wow!!! Almost a month and no answers. Nobody can say how to set up a HTTPS?
From @Suncatcher on July 31, 2017 12:52
Is it Docker-specific setting or the way is the same for all versions?
I think Google will be your best friend for that case. Few links:
- https://github.com/docker-library/wordpress/issues/46#issuecomment-311275059
- https://tech.acseo.co/sites-https-docker-nginx-lets-encrypt/
- https://github.com/MarvAmBass/docker-nginx-ssl-secure
From @Suncatcher on July 31, 2017 13:15
The first link is about Apache, and the latter is about securing separate nginx Docker container. In our case nginx is included in wallabag image. Is it?
From @Suncatcher on July 31, 2017 15:20
I see here on Dockerhub we have SSL settings sample for nginx:
server {
listen 443;
server_name wallabag.foo.bar;
ssl on;
ssl_certificate /etc/letsencrypt/live/wallabag.foo.bar/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/wallabag.foo.bar/privkey.pem;
location / {
proxy_pass http://wallabag;
proxy_set_header X-Forwarded-Host $server_name;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-For $remote_addr;
}
}
However, where should we put it? In Docker-file? In docker-compose? Somewhere inside wallabag container? In running state or in stopped? HTTPS thing should be somehow highlighted in documentation.
This should goes to the docker-composer of wallabag/docker. In fact, I'll move that issue in the correct repo.
I use traefik as reverse proxy on top of my containers and it is in charge of ssl termination (it supports letsencrypt). Between traefik and containers it's basic http connection on the docker network interface only.
Do you have many containers? What is the advantage of traefic?
Yes, a dozen at least.
Traefik is interesting as it integrates docker containers (but also other such as kubernetes, consul, etc) on the fly and provides ssl endpoint (letsencrypt or traditional certificates) and can even be used as traditional reverse proxy.
@j0k3r this should go into a nginx configuration. this is only for the reverse proxy. making wallabag public is a thing of a reverse proxy using a plain http connection to the container in my opinion. but lets discuss it :)
in a Wallabag Docker container nginx acts like a reverse proxy by default?
@Suncatcher nope... you should use a reverse proxy for accessing the wallabag container... if you really want to make it public available. there you can you traefik or nginx or something for ssl and stuff. the wallabag image is just for accepting the connection.
I highly recommend you Traefik for this as reverse proxy: https://docs.traefik.io/user-guide/docker-and-lets-encrypt/
I highly recommend you Traefik for this as reverse proxy: https://docs.traefik.io/user-guide/docker-and-lets-encrypt/
I followed the instruction in your link. But unfortunately I was not able to make it work. I am a newbie with docker as well... thanks for your help. There is no real error message. In the browser I get 'gateway timeout'.
version: '3'
networks:
web:
volumes:
traefik-acme:
wallabag-maria-db:
services:
wallabag:
image: wallabag/wallabag
networks:
- web
- default
expose:
- "80"
labels:
traefik.backend: "wallabag"
traefik.docker.network: "traefik_default"
traefik.docker.network: "web"
traefik.frontend.rule: "Host:my.domain.com"
traefik.enable: "true"
traefik.port: "80"
traefik.default.protocol: "http"
volumes:
- /opt/wallabag/images:/var/www/wallabag/web/assets/images
environment:
- MYSQL_ROOT_PASSWORD=wallaroot
- SYMFONY__ENV__DATABASE_DRIVER=pdo_mysql
- SYMFONY__ENV__DATABASE_HOST=db
- SYMFONY__ENV__DATABASE_PORT=3306
- SYMFONY__ENV__DATABASE_NAME=wallabag
- SYMFONY__ENV__DATABASE_USER=wallabag
- SYMFONY__ENV__DATABASE_PASSWORD=pass
- SYMFONY__ENV__MAILER_HOST=127.0.0.1
- SYMFONY__ENV__MAILER_USER=~
- SYMFONY__ENV__MAILER_PASSWORD=~
- [email protected]
- SYMFONY__ENV__FOSUSER_REGISTRATION=false
- SYMFONY__ENV__DOMAIN_NAME=my.domain.com
db:
image: mariadb
environment:
- MYSQL_ROOT_PASSWORD=wallaroot
volumes:
- /opt/wallabag/data:/var/lib/mysql
redis:
image: redis:alpine
You need to add traefik to the related network
See https://docs.traefik.io/configuration/backends/docker/#using-docker-compose and the message at the end of the page:
When running inside a container, Træfik will need network access through:
docker network connect <network> <traefik-container>
@nsteinmetz I also use traefik for all of my containers. But with wallabag I encountered an issue, when I try:
curl -I https://my.domain
I get:
HTTP/2 302 cache-control: no-cache, private content-type: text/html; charset=UTF-8 date: Wed, 05 Dec 2018 11:51:54 GMT location: http://my.domain server: nginx set-cookie: PHPSESSID=71a90d0ec85a887982f2adb7785f4770; path=/; HttpOnly strict-transport-security: max-age=315360000; includeSubdomains; preload vary: Accept-Encoding x-content-type-options: nosniff x-frame-options: DENY x-powered-by: PHP/7.2.10 x-xss-protection: 1; mode=block
This is also giving me headaches with the android app telling me: "wallabag service not found -- check url". Any idea on why this is happening?
@rbcolom
Seems you have a redirect from https to http ?!
Can you share your docker-compose.yml for wallabag and/or traefik and your traefik.toml so that I can review and compare it to mine ?
Is your service available on the http url ?
@nsteinmetz
Certainly, here is the docker-compose:
wallabag:
image: wallabag/wallabag
container_name: wallabag
healthcheck:
test: ["CMD", "curl" , "-f", "http://localhost:80"]
interval: 30s
timeout: 10s
retries: 5
environment:
- TZ=it-IT
- PUID=1000
- PGID=1000
- "SYMFONY__ENV__FOSUSER_REGISTRATION=false"
- "SYMFONY__ENV__DOMAIN_NAME=https://my.domain"
- "SYMFONY__ENV__MAILER_HOST=~"
- "SYMFONY__ENV__MAILER_USER=~"
- "SYMFONY__ENV__MAILER_PASSWORD=~"
- "SYMFONY__ENV__FROM_EMAIL=~"
networks:
- traefik_proxy
volumes:
- /etc/localtime:/etc/localtime:ro
- /home/roberto/DockerConf/wallabag/images:/var/www/wallabag/web/assets/images
- /home/roberto/DockerConf/wallabag/data:/var/www/wallabag/data
labels:
- "traefik.enable=true"
- "traefik.backend=wallabag"
- "traefik.frontend.rule=Host:my.domain"
- "traefik.port=80"
- "traefik.protocol=http"
- "traefik.docker.network=traefik_proxy"
- "traefik.frontend.headers.SSLRedirect=true"
- "traefik.frontend.headers.STSSeconds=315360000"
- "traefik.frontend.headers.browserXSSFilter=true"
- "traefik.frontend.headers.contentTypeNosniff=true"
- "traefik.frontend.headers.forceSTSHeader=true"
- "traefik.frontend.headers.SSLHost=my.domain"
- "traefik.frontend.headers.STSIncludeSubdomains=true"
- "traefik.frontend.headers.STSPreload=true"
- "traefik.frontend.headers.frameDeny=true"
- "traefik.frontend.redirect.entryPoint=https"
and here is the relevant traefik.toml part:
# Force HTTPS
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.http.redirect]
entryPoint = "https"
[entryPoints.https]
address = ":443"
compress = true
[entryPoints.https.tls]
For all of my services I use a http to https redirect. BTW thanks for the help, this is driving me nuts.
@rbcolom take care about your environment variables - you should not have quotes - cf https://docs.docker.com/compose/compose-file/#environment
For my wallabag docker-compose.yml:
version: '2'
services:
wallabag:
image: wallabag/wallabag
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=XXX
- POPULATE_DATABASE=False
- SYMFONY__ENV__DATABASE_DRIVER=pdo_pgsql
- SYMFONY__ENV__DATABASE_HOST=db
- SYMFONY__ENV__DATABASE_PORT=5432
- SYMFONY__ENV__DATABASE_NAME=wallabag
- SYMFONY__ENV__DATABASE_USER=wallabag
- SYMFONY__ENV__DATABASE_PASSWORD=XXX
- SYMFONY__ENV__DOMAIN_NAME=https://wallabag.domain.tld
labels:
- "traefik.backend=steinmetz-wallabag"
- "traefik.frontend.rule=Host:wallabag.domain.tld"
- "traefik.port=80"
- "traefik.protocol=http"
- "traefik.frontend.entryPoints=http,https"
depends_on:
- db
- redis
restart: always
db:
image: postgres:9.6-alpine
environment:
- POSTGRES_PASSWORD=XXX
volumes:
- /srv/www/steinmetz.fr/w/db:/var/lib/postgresql/data
labels:
- "traefik.enable=false"
restart: always
redis:
image: redis:alpine
labels:
- "traefik.enable=false"
restart: always
How do you launch traeik ? I don't see the docker integration/activation ?
On my side, I deploy traefik as a binary - not as a docker container - managed by systemd and with follwoing traefik.toml:
defaultEntryPoints = ["http", "https"]
traefikLogsFile = "/var/log/traefik.log"
logLevel = "ERROR"
[accessLog]
filePath = "/var/log/traefik_access.log"
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.http.redirect]
entryPoint = "https"
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
[...]
[docker]
endpoint = "unix:///var/run/docker.sock"
domain = "docker.localhost"
watch = true
Pardon me, I cut out the wallabag section in the docker-compose file, traefik for me is a docker instance as well. I tried your configuration (but still using a traefik docker image) on a different machine and I still get the same results. Can you confirm me that you're able to use the android application?
if you use a traefik docker image, you need to connect traefik to your wallabag network (or the opposite).
I use the android version without any issue.
Sorry, I didn't explain myself properly. With my current configuration (the one in the comments above) wallabag is up and running, I can access it through my domain without any problem.
What doesn't work is the android app. Investigating a bit, I found out that the POST request wallabag.domain/login ignores the reverse proxy and passing via http.
so when I do:
curl -I https://my.domain
I get:
location: http://my.domain/login
I think the problem is that the Symfony setting for trusting the reverse proxy is not set. Instructions for that are here: https://symfony.com/doc/3.4/deployment/proxies.html
I manually added that in my Docker in the web/app.php and it works. That's probably not the best place to add it, but I'm not familiar with Symfony 3 code organization.
Also, what I've seen in other PHP projects is that they add an environment variable called trusted_proxies, which can be used to set this value dynamically (from Docker for example).
I've upgraded to the 2.1.0 version of the wallabag android app and it is now working. I'm using the latest docker image of wallabag and the reverse proxy is traefik.
But does the redirect from https://my.domain to http://my.domain/login still happen?
@rolisz Yes, it still occurs, the response is the same. If you need any other info/data, I'll be glad to provide it to you.
@rolisz this downgrading when redirecting is causing issues for anyone using the wallabag android app in android 9 FYI see https://github.com/wallabag/android-app/issues/756, https://github.com/wallabag/wallabag/issues/2273, and https://github.com/wallabag/docker/issues/110 and the only workaround is apparently deprecated by https://github.com/wallabag/wallabag/commit/80336f77fd6ef72dafe20b35b74d74d06592c06f
Adding the following traefik frontend redirects via labels on my wallabag container worked for me. even though wallabag tries to downgrade to http on redirect, my frontend now upgrades it back to https.
- "traefik.frontend.redirect.regex=^http://wallabag.example.com/(.*)"
- "traefik.frontend.redirect.replacement=https://wallabag.example.com/$$1"
- "traefik.frontend.redirect.permanent=true"
norweeg@my-pc$ curl -I https://wallabag.example.com
HTTP/2 302
cache-control: no-cache, private
content-type: text/html; charset=UTF-8
date: Sun, 03 Feb 2019 19:23:50 GMT
location: http://wallabag.example.com/login
referrer-policy: no-referrer
server: nginx
set-cookie: PHPSESSID=574fb5e6fb8c7a092532a93c98294d2b; path=/; HttpOnly
strict-transport-security: max-age=15552000
x-powered-by: PHP/7.2.13
norweeg@my-pc$ curl -I http://wallabag.example.com/login
HTTP/1.1 307 Temporary Redirect
Location: https://wallabag.example.com:443/login
Date: Sun, 03 Feb 2019 19:24:01 GMT
Content-Length: 18
Content-Type: text/plain; charset=utf-8
norweeg@my-pc$ curl -I https://wallabag.example.com:443/login
HTTP/2 200
cache-control: no-cache, private
content-type: text/html; charset=UTF-8
date: Sun, 03 Feb 2019 19:24:22 GMT
referrer-policy: no-referrer
server: nginx
set-cookie: PHPSESSID=e5b601c4811270133e530c0d986e7280; path=/; HttpOnly
strict-transport-security: max-age=15552000
x-powered-by: PHP/7.2.13
@norweeg I still have the problem even with your suggestion.
I found that traefik.frontend.headers.SSLRedirect have the same behaviour (308 + correct HTTPS URL), but in both cases the Android app keeps throwing the error message.
@Chostakovitch huh.. that's strange because I don't touch that option, but I stopped getting the error once my wallabag frontend sent a http 301 redirect instead of 302 redirect from http to https (the redirect at the entrypoint level wasn't sufficient). I probably forgot something in my earlier post, so here's my docker-compose service template for my wallabag service that has worked for me:
version: '3.5'
services:
wallabag:
image: wallabag/wallabag:latest
container_name: wallabag
networks:
- wallabag
restart: unless-stopped
env_file:
- ../configs/wallabag.env
expose:
- "80"
labels:
- traefik.enable=true
- traefik.backend=wallabag
- traefik.frontend.rule=Host:${WALLABAG_DOMAIN}
- "traefik.frontend.redirect.regex=^http://${WALLABAG_DOMAIN}/(.*)"
- "traefik.frontend.redirect.replacement=https://${WALLABAG_DOMAIN}/$$1"
- traefik.frontend.redirect.permanent=true
- traefik.frontend.passHostHeader=true
- traefik.frontend.whiteList.useXForwardedFor=true
- traefik.frontend.headers.SSLProxyHeaders=X-Forwarded-Proto:https
- traefik.docker.network=wallabag
- traefik.port=80
- com.centurylinklabs.watchtower.enable=true
depends_on:
- wallabag-db
- wallabag-redis
healthcheck:
test: ["CMD-SHELL", "curl -f http://wallabag:80/login > /dev/null || exit 1"]
interval: 15s
timeout: 10s
retries: 5
start_period: 15s
volumes:
- wallabag-images:/var/www/wallabag/web/assets/images
- wallabag-data:/var/www/wallabag/data
- wallabag-logs:/var/www/wallabag/var/logs
edit: oops! I'm getting my threads on this issue mixed up. Was referring to an earlier post on https://github.com/wallabag/android-app/issues/756#issuecomment-462996975