Stack:
serverX
docker
traefik
x-site.com
redirect :80->:443
https://x-site.com/* -> x-site docker container
wss://x-site.com/ws proxy -> ws://external.websocket.com:8083/ws HOW TO?
y-site.com
...
external.websocket.com - works perfectly with all kinds of mqtt,ws clients, except web
software: emqx
listens: ws:8083 mqtt:1883
protocol: ws, mqtt
proxy protocol support: on
docker-compose.yml
version: '3.7'
services:
router:
container_name: router
image: traefik:v2.6
restart: on-failure:5
ports:
- target: 80
published: 80
mode: host
- target: 443
published: 443
mode: host
- target: 8080
published: 8080
mode: host
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./router:/etc/traefik
x-site:
container_name: x-site
image: backend
restart: on-failure:5
env_file:
- /.default.env
- /.server.env
- /root/env/x-site.env
labels:
traefik.enable: true
traefik.http.routers.x-site.rule: Host(`x-site.com`)
traefik.http.routers.x-site.entrypoints: web,websecure
traefik.http.routers.x-site.tls: true
# tried service loadbalancer and etc
# traefik.http.routers.ws_x-site.rule: Host(`x-site.com`) && PathPrefix(`/ws`)
# traefik.http.routers.ws_x-site.entrypoints: websecure
# traefik.http.routers.ws_x-site.service: websocket_x-site
# traefik.http.services.websocket_x-site.loadBalancer.server.url: ws://external.websocket.com:8083/ws
traefik.yaml
api:
insecure: true
dashboard: true
entryPoints:
web:
address: ":80"
http:
redirections:
entryPoint:
to: websecure
scheme: https
permanent: true
transport:
respondingTimeouts:
readTimeout: 10
writeTimeout: 10
idleTimeout: 10
lifeCycle:
requestAcceptGraceTimeout: 5
graceTimeOut: 5
websecure:
address: ":443"
transport:
respondingTimeouts:
readTimeout: 300
writeTimeout: 3600
idleTimeout: 180
lifeCycle:
requestAcceptGraceTimeout: 30
graceTimeOut: 30
providers:
docker:
endpoint: unix:///var/run/docker.sock
exposedByDefault: false
file:
filename: /etc/traefik/cert.yaml
log:
level: ERROR
Related
Unable to routing external ip/port
I'm following this guide and unable to route the external IP into the subdomain, resulting to nothing while internal port (installed portainer in docker) seems working. Exposing to the public is my next plan. Following is my yml config
docker-compose.yml
Exposed 80 and 443 port from the router, DNS name server also pointed on my digitalocean then pointed into my traefik-dashboard.local.example.com -> public-IP by using A-record
version: '3'
services:
traefik:
image: traefik:latest
container_name: traefik
restart: unless-stopped
security_opt:
- no-new-privileges:true
networks:
- proxy
ports:
- 80:80
- 443:443
environment:
- DO_AUTH_TOKEN=TOKEN
volumes:
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
- /root/container/traefik/data/traefik.yml:/traefik.yml:ro
- /root/container/traefik/data/traefik.yml:/traefik.yml:ro
- /root/container/traefik/data/acme.json:/acme.json
- /root/container/traefik/data/config.yml:/config.yml:ro
labels:
- "traefik.enable=true"
- "traefik.http.routers.traefik.entrypoints=http"
- "traefik.http.routers.traefik.rule=Host(`traefik-dashboard.local.example.com`)"
- "traefik.http.middlewares.traefik-auth.basicauth.users=admin:password"
- "traefik.http.middlewares.traefik-https-redirect.redirectscheme.scheme=https"
- "traefik.http.middlewares.sslheader.headers.customrequestheaders.X-Forwarded-Proto=https"
- "traefik.http.routers.traefik.middlewares=traefik-https-redirect"
- "traefik.http.routers.traefik-secure.entrypoints=https"
- "traefik.http.routers.traefik-secure.rule=Host(`traefik-dashboard.local.example.com`)"
- "traefik.http.routers.traefik-secure.middlewares=traefik-auth"
- "traefik.http.routers.traefik-secure.tls=true"
- "traefik.http.routers.traefik-secure.tls.certresolver=digitalocean"
- "traefik.http.routers.traefik-secure.tls.domains[0].main=local.example.com"
- "traefik.http.routers.traefik-secure.tls.domains[0].sans=*.local.example.com"
- "traefik.http.routers.traefik-secure.service=api#internal"
expose:
- 80
networks:
proxy:
external: true
data/traefik.yml
api:
dashboard: true
debug: true
insecure: true
entryPoints:
http:
address: ":80"
https:
address: ":443"
serversTransport:
insecureSkipVerify: true
providers:
docker:
endpoint: "unix:///var/run/docker.sock"
exposedByDefault: false
file:
filename: /config.yml
accessLog: {}
log:
level: debug
certificatesResolvers:
digitalocean:
acme:
email: email#example.com
storage: acme.json
dnsChallenge:
provider: digitalocean
delayBeforeCheck: 0
#resolvers:
# - "1.1.1.1:53"
# - "1.0.0.1:53"
pilot:
dashboard: false
metrics:
prometheus:
entryPoint: traefik
accessLog:
filePath: "/var/log/traefik/access.log"
filters:
statusCodes:
- "400-600"
` ``api:
dashboard: true
debug: true
insecure: true
entryPoints:
http:
address: ":80"
https:
address: ":443"
serversTransport:
insecureSkipVerify: true
providers:
docker:
endpoint: "unix:///var/run/docker.sock"
exposedByDefault: false
file:
filename: /config.yml
accessLog: {}
log:
level: debug
certificatesResolvers:
digitalocean:
acme:
email: email#example.com
storage: acme.json
dnsChallenge:
provider: digitalocean
delayBeforeCheck: 0
#resolvers:
# - "1.1.1.1:53"
# - "1.0.0.1:53"
pilot:
dashboard: false
metrics:
prometheus:
entryPoint: traefik
accessLog:
filePath: "/var/log/traefik/access.log"
filters:
statusCodes:
- "400-600"
The dashboard appeared with healthy server,
data/config.yml
I'm toggling this config on/off and the problem still persists.
http:
routers:
pihole:
entryPoints:
- "https"
rule: "Host(`pihole.local.example.com`)"
middlewares:
- default-headers
- addprefix-pihole
tls: {}
service: pihole
services:
pihole:
loadBalancer:
servers:
- url: "http://192.168.0.20:80"
passHostHeader: true
middlewares:
addprefix-pihole:
addPrefix:
prefix: "/admin"
https-redirect:
redirectScheme:
scheme: https
default-headers:
headers:
frameDeny: true
sslRedirect: true
browserXssFilter: true
contentTypeNosniff: true
forceSTSHeader: true
stsIncludeSubdomains: true
stsPreload: true
stsSeconds: 15552000
customFrameOptionsValue: SAMEORIGIN
customRequestHeaders:
X-Forwarded-Proto: https
Already assigned A record in pi-hole, dns, seems doesn't do anything magic, the pihole.local.example.com still appeared blank.
Let me know if there's anything wrong with my config.
Attached below is my log
https://pastebin.com/raw/R1w9jR7U
I am testing treafik to set it up for exposing my docker containers with SSL.
I seams to mostly work but I am having some issues http to https redirect. I have middleware that shows up in the dashboard as successful but when I go http option of the address I get 404
Here is my docker-compose.yml for traefik
version: "3.3"
services:
traefik:
image: traefik:v2.5
restart: always
container_name: traefik
ports:
- "80:80" # <== http
- "8080:8080" # <== :8080 is where the dashboard runs on
- "443:443" # <== https
command:
- --api.insecure=false # <== Enabling insecure api, NOT RECOMMENDED FOR PRODUCTION
- --api.dashboard=true # <== Enabling the dashboard to view services, middlewares, routers, etc.
- --api.debug=true # <== Enabling additional endpoints for debugging and profiling
- --log.level=DEBUG # <== Setting the level of the logs from traefik
- --providers.docker=true # <== Enabling docker as the provider for traefik
- --providers.docker.exposedbydefault=false # <== Don't expose every container to traefik
- --providers.file.filename=/config/dynamic.yaml # <== Referring to a dynamic configuration file
- --providers.docker.network=web # <== Operate on the docker network named web
- --entrypoints.web.address=:80 # <== Defining an entrypoint for port :80 named web
- --entrypoints.web.http.redirections.entryPoint.to=web-secure
- --entrypoints.web.http.redirections.entryPoint.scheme=https
- --entrypoints.web.http.redirections.entrypoint.permanent=true
- --entrypoints.web-secured.address=:443 # <== Defining an entrypoint for https on port :443 (not really nee$
- --certificatesresolvers.mytlschallenge.acme.tlschallenge=true # <== Enable TLS-ALPN-01 (not really needed)
- --certificatesresolvers.mytlschallenge.acme.email=email#domain.com # <== Set your email (not really needed)
- --certificatesresolvers.mytlschallenge.acme.storage=/letsencrypt/acme.json # <== SSL stuff we don't need.
volumes:
- ./letsencrypt:/letsencrypt # <== Volume for certs (TLS) (not really needed)
- /var/run/docker.sock:/var/run/docker.sock # <== Volume for docker admin
- ./config/:/config # <== Volume for dynamic conf file, **ref: line 27
networks:
- web # <== Placing traefik on the network named web, to access containers on this network
labels:
- "traefik.enable=true" # <== Enable traefik on itself to view dashboard and assign subdomain to$
- "traefik.http.routers.api.rule=Host(`traefik.testing.domain.com`)" # <== Setting the domain for the d$
- "traefik.http.routers.api.service=api#internal" # <== Enabling the api to be a service to acce$
networks:
web:
external: true
name: web
Here is the config/dynamic.yaml for traefik to set up middleware
## Setting up the middleware for redirect to https ##
http:
middlewares:
httpsredirect:
redirectScheme:
scheme: https
permanent: true
And here is test docker containers docker-compose.yml
version: '3.3'
services:
whoami:
# A container that exposes an API to show its IP address
image: traefik/whoami
networks:
- web
labels:
- "traefik.enable=true"
- "treafik.http.routers.whoami.entrypoints=web,web-secure"
- "traefik.http.routers.whoami.rule=Host(`whoami.testing.domain.com`)"
- "traefik.http.routers.whoami.tls=true"
- "traefik.http.routers.whoami.middlewares=httpsredirect#file" # <== This is a middleware to redirect to htt$
- "traefik.http.routers.whoami.tls.certresolver=mytlschallenge"
networks:
web:
external: true
name: web
Try the following from redirect regex
Docker
# Redirect with domain replacement
# Note: all dollar signs need to be doubled for escaping.
labels:
- "traefik.http.middlewares.test-redirectregex.redirectregex.regex=^https://localhost/(.*)"
- "traefik.http.middlewares.test-redirectregex.redirectregex.replacement=http://mydomain/$${1}"
For kubernetes
---
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: http-to-https-redirect
spec:
redirectRegex:
regex: ^http://(www.)?yourdomain.com/(.*)
replacement: https://yourdomain.com
permanent: true
And you inject the middleware in your ingress route
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: ingressroute
spec:
tls: {}
entryPoints:
- web
- websecure
routes:
- match: "HostRegexp(`{sub:(www.)?}yourdomain.com`) && PathPrefix(`/`)"
kind: Rule
services:
- name: your-service
port: 80
Im deploying my docker container via my docker compose file.
When i initially deploy my app it creates a load balancer but as type "network". I cannot do a redirect to https with this type.
I want my load balancer to be created as a type "application" and then setup the redirect from http to https.
My container will still be listening to port 80.
Bonus: i would like to deploy and also attach my SSL cert in my compose file so that its all ready on a fresh deploy.
As you can see ive tried a few things but cant get it to work.
Thanks
version: '3.8'
services:
web:
container_name: auction_web
image: <ECR Image>
# x-aws-pull_credentials: arn:aws:secretsmanager:xxxxxxxxxxxx
depends_on:
- redis
ports:
# - "80:80" - tried this
# - "443:443" - tried this
- target: 80
x-aws-protocol: http
- target: 443
x-aws-protocol: https
# - published: 80
# protocol: "http"
# x-aws-alb-default-actions:
# - type: redirect
# host: '<domain>'
# port: 443
# protocol: HTTPS
# status-code: HTTP_301
# - published: 443
# protocol: "https"
# x-aws-acm-certificate: <cert name>
deploy:
resources:
limits:
cpus: '1'
memory: 4096M
Please try this:
Define ports with "80:80" and "443:443" and nothing else.
Add the following section at the bottom of the docker-compose file:
x-aws-cloudformation:
Resources:
Web443Listener:
Properties:
Certificates:
- CertificateArn: "<certificate ARN>"
Protocol: HTTPS
Port: 443
Web80Listener:
Properties:
DefaultActions:
- Type: redirect
RedirectConfig:
Port: 443
Protocol: HTTPS
StatusCode: HTTP_301
x-aws-cloudformation:
Resources:
App80Listener:
Properties:
Port: 80
Protocol: HTTP
LoadBalancerArn:
Ref: LoadBalancer
DefaultActions:
- Type: redirect
RedirectConfig:
Port: 443
Protocol: HTTPS
StatusCode: HTTP_301
Type: AWS::ElasticLoadBalancingV2::Listener
App443Listener:
Properties:
Port: 443
Protocol: HTTPS
LoadBalancerArn:
Ref: LoadBalancer
DefaultActions:
- ForwardConfig:
TargetGroups:
- TargetGroupArn:
Ref: App8080TargetGroup
Type: forward
Certificates:
- CertificateArn: "<arn for cert>"
Type: AWS::ElasticLoadBalancingV2::Listener
App8080TargetGroup:
Properties:
Name: 'jenkins-tg'
Port: 8080
Protocol: HTTP
Tags:
- Key: com.docker.compose.project
Value: jenkins
TargetType: ip
VpcId: vpc-d21afbbb
HealthCheckPath: '/login'
Type: AWS::ElasticLoadBalancingV2::TargetGroup
I use Docker Swarm to deploy 3 instances of RabbitMQ and Consul for the peer discovery.
version: '3.7'
services:
rabbitmq-1:
image: rabbitmq:3.8.9-alpine
hostname: "rabbitmq-1"
environment:
- RABBITMQ_ERLANG_COOKIE="SECRET_COOKIE"
networks:
- prod-net
configs:
- source: rabbitmq-config
target: /etc/rabbitmq/rabbitmq.conf
- source: rabbitmq-plugins-config
target: /etc/rabbitmq/enabled_plugins
volumes:
- /shared/rabbitmq/1/config:/etc/rabbitmq
- /shared/rabbitmq/1/data:/var/lib/rabbitmq
deploy:
replicas: 1
rabbitmq-2:
image: rabbitmq:3.8.9-alpine
hostname: "rabbitmq-2"
environment:
- RABBITMQ_ERLANG_COOKIE="SECRET_COOKIE"
networks:
- prod-net
configs:
- source: rabbitmq-config
target: /etc/rabbitmq/rabbitmq.conf
- source: rabbitmq-plugins-config
target: /etc/rabbitmq/enabled_plugins
volumes:
- /shared/rabbitmq/2/config:/etc/rabbitmq
- /shared/rabbitmq/2/data:/var/lib/rabbitmq
deploy:
replicas: 1
rabbitmq-3:
image: rabbitmq:3.8.9-alpine
hostname: "rabbitmq-3"
environment:
- RABBITMQ_ERLANG_COOKIE="SECRET_COOKIE"
networks:
- prod-net
configs:
- source: rabbitmq-config
target: /etc/rabbitmq/rabbitmq.conf
- source: rabbitmq-plugins-config
target: /etc/rabbitmq/enabled_plugins
volumes:
- /shared/rabbitmq/3/config:/etc/rabbitmq
- /shared/rabbitmq/3/data:/var/lib/rabbitmq
deploy:
replicas: 1
networks:
consul-net:
external: true
name: prod-net
configs:
rabbitmq-config:
external: true
rabbitmq-plugins-config:
external: true
RabbitMQ registers itself with Consul by its hostname so that the nodes can discover each other. So all the hostnames must resolve on all nodes. In the example above I'm using the same value for both the hostname and the service name to achieve this. But I would like to use a more compact way to represent a cluster by using a replicas: 3 parameter.
version: '3.7'
services:
rabbitmq:
image: rabbitmq:3.8.9-alpine
hostname: "rabbitmq-{{.Task.Slot}}"
networks:
- prod-net
configs:
- source: rabbitmq-config
target: /etc/rabbitmq/rabbitmq.conf
- source: rabbitmq-plugins-config
target: /etc/rabbitmq/enabled_plugins
deploy:
replicas: 3
restart_policy:
condition: any
networks:
prod-net:
external: true
configs:
rabbitmq-config:
external: true
rabbitmq-plugins-config:
external: true
Sadly in this case the hostnames are not anymore resolvable by docker DNS and the nodes cannot see each other. It there a way to achieve this ?
Edit.1:
Using these in rabbitmq-config gives the errors bellow:
cluster_formation.peer_discovery_backend = rabbit_peer_discovery_dns
cluster_formation.dns.hostname = tasks.rabbitmq
2020-10-15 22:06:01.573 [error] <0.272.0> attempted to contact: ['rabbit#rabbitmq-3','rabbit#rabbitmq-2']
2020-10-15 22:06:01.574 [error] <0.272.0> rabbit#rabbitmq-3:
2020-10-15 22:06:01.574 [error] <0.272.0> * unable to connect to epmd (port 4369) on rabbitmq-3: couldn't resolve hostname
2020-10-15 22:06:01.574 [error] <0.272.0> rabbit#rabbitmq-2:
2020-10-15 22:06:01.575 [error] <0.272.0> * unable to connect to epmd (port 4369) on rabbitmq-2: couldn't resolve hostname
Edit.2:
rabbitmq.conf using Consul peer discovery
# Credentials
default_user = admin
default_pass = Pa$$w0rd1
loopback_users.admin = false
vm_memory_high_watermark.absolute = 1024MiB
disk_free_limit.absolute = 5GB
loopback_users.guest = false
# TLS Support in RabbitMQ
listeners.ssl.default = 5671
# Disables non-TLS listeners, only TLS-enabled clients will be able to connect
listeners.tcp = none
ssl_options.cacertfile = /etc/rabbitmq/ca_certificate.pem
ssl_options.certfile = /etc/rabbitmq/server_certificate.pem
ssl_options.keyfile = /etc/rabbitmq/server_key.pem
ssl_options.password = Pa$$phr#se
ssl_options.verify = verify_peer
ssl_options.fail_if_no_peer_cert = true
# TLS Support in RabbitMQ UI
management.ssl.port = 15671
management.ssl.cacertfile = /etc/rabbitmq/ca_certificate.pem
management.ssl.certfile = /etc/rabbitmq/server_certificate.pem
management.ssl.keyfile = /etc/rabbitmq/server_key.pem
management.ssl.password = Pa$$phr#se
management.ssl.verify = verify_none
management.ssl.fail_if_no_peer_cert = false
management.ssl.honor_cipher_order = true
management.ssl.honor_ecc_order = true
management.ssl.client_renegotiation = false
management.ssl.secure_renegotiate = true
cluster_partition_handling = autoheal
# Consul peer discovery
cluster_formation.peer_discovery_backend = rabbit_peer_discovery_consul
# Consul host (hostname or IP address)
cluster_formation.consul.host = consul_client
# Service name (as registered in Consul) defaults to "rabbitmq"
cluster_formation.consul.svc = rabbitmq
# Compute service address (if not specify it below)
cluster_formation.consul.svc_addr_auto = true
cluster_formation.consul.use_longname = true
cluster_formation.consul.svc_ttl = 50
cluster_formation.consul.deregister_after = 100
cluster_formation.node_cleanup.only_log_warning = true
Or using DNS peer discovery:
#DNS Peer Discovery
cluster_formation.peer_discovery_backend = rabbit_peer_discovery_dns
cluster_formation.dns.hostname = tasks.rabbitmq
To achieve DNS resolve between RabbitMQ replicas, need to modify /etc/hosts of each RabbitMQ container.
This will allow to form RabbitMQ cluster via rabbtimq configuration file.
See demo on how to create RabbitMQ cluster using single docker swarm service. I removed references to Consul and TLS from rabbitmq.conf for simplicity.
I spent the last 3 days trying to use traefik for HTTPS, load balancer, and to connect portainer and other docker containers in swarm mode. It is a home-server cluster made with 4 raspberrys, and what I want is the SSL auto-certificate function, and the HTTP to HTTPS redirection. For that purpose I've created a traefik.toml file:
logLevel = "DEBUG"
defaultEntryPoints = ["http", "https"]
[web]
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.http.redirect]
entryPoint = "https"
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
[acme]
email = "xxx#xxx.com"
storage = "acme.json"
entryPoint = "https"
OnHostRule = true
[acme.httpChallenge]
entryPoint = "http"
[docker]
domain = "traefik" #<---- WHAT SHOULD I WRITE HERE?
watch = true
swarmmode = true
I don't know what should I write in the DOMAIN variable. I use NoIP as my dynamic DNS provider. Should I write the domain I get from them? and that should work inside my network? i.e. accesing from a computer inside my network with: 192.168.11.100
And I also have a docker-compose.yml file:
version: "3.4"
services:
proxy:
image: traefik:latest
command:
- "--api"
- "--entrypoints=Name:http Address::80 Redirect.EntryPoint:https"
- "--entrypoints=Name:https Address::443 TLS"
- "--defaultentrypoints=http,https"
- "--acme"
- "--acme.storage=/etc/traefik/acme/acme.json"
- "--acme.entryPoint=https"
- "--acme.httpChallenge.entryPoint=http"
- "--acme.onHostRule=true"
- "--acme.onDemand=false"
- "--acme.email=xxx#xxx.com"
- "--docker"
- "--docker.swarmMode"
- "--docker.domain=traefik.localhost" <- WHAT SHOULD I PUT IN HERE??
- "--docker.watch"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /mnt/traefik/acme.json:/etc/traefik/acme/acme.json
networks:
- appnet
ports:
- target: 80
published: 80
mode: host
- target: 443
published: 443
mode: host
- target: 8080
published: 8080
mode: host
deploy:
mode: global
placement:
constraints:
- node.role == manager
update_config:
parallelism: 1
delay: 10s
restart_policy:
condition: on-failure
networks:
appnet:
external: true
Deploy the stack, then I write in firefox in another computer 192.168.11.100, and I can see the "Welcome to nginx page". No HTTPS by the way. Try 192.168.11.100:8080 for the traefik dashboard. It is there, but again only HTTP.
If I deploy portainer, looks like it connects with traefik (at least appear in the dashboard), but again only HTTP.
Here's the logs for the traefik container after deploying portainer:
time="2019-02-19T11:32:52Z" level=error msg="Unable to obtain ACME certificate for domains \"portainer.com\" detected thanks to rule \"Host:portainer.com\" : unable to generate a certificate for the domains [portainer.com]: acme: Error -> One or more domains had a problem:\n[portainer.com] acme: error: 403 :: urn:ietf:params:acme:error:unauthorized :: Invalid response from http://portainer.com/.well-known/acme-challenge/eDN0Z2VJRzuZm9wiAbar1BOVHLPJ5qPYKBpwfuJOtdY: \"<!doctype html><html><head><meta charset=\\\"utf-8\\\"><meta http-equiv=\\\"x-ua-compatible\\\" content=\\\"ie=edge\\\"><meta name=\\\"viewport\\\" cont\", url: \n"
time="2019-02-19T11:33:15Z" level=error msg="Unable to obtain ACME certificate for domains \"portainer.com\" detected thanks to rule \"Host:portainer.com\" : unable to generate a certificate for the domains [portainer.com]: acme: Error -> One or more domains had a problem:\n[portainer.com] acme: error: 403 :: urn:ietf:params:acme:error:unauthorized :: Invalid response from http://portainer.com/.well-known/acme-challenge/Of6CWm4zvCdPo0BFPTxapEVXPU-qf7hhl1f6NCUTmQw: \"<!doctype html><html><head><meta charset=\\\"utf-8\\\"><meta http-equiv=\\\"x-ua-compatible\\\" content=\\\"ie=edge\\\"><meta name=\\\"viewport\\\" cont\", url: \n"
Am I missing something?