wip: portainer
This commit is contained in:
parent
23e60b1a75
commit
b9837cc947
@ -3,10 +3,10 @@ title: About gtz blog
|
|||||||
author: Asger Gitz-Johansen
|
author: Asger Gitz-Johansen
|
||||||
---
|
---
|
||||||
|
|
||||||
I am a software engineer from Denmark working at [GomSpace](https://gomspace.com/home.aspx).
|
I am a software engineer from Denmark working at [GomSpace](https://gomspace.com/home.aspx). This is just my simple
|
||||||
This is just my simple blog that I use for letting out "blogging-steam".
|
blog that I use for letting out "blogging-steam". I write GNU/Linux based tutorials and sometimes I write opinion
|
||||||
I write GNU/Linux based tutorials and sometimes I write opinion pieces.
|
pieces. These posts are mostly for my own sake, but I hope you find my stuff useful.
|
||||||
I hope you find my stuff useful.
|
|
||||||
If you want more from me, check my links:
|
If you want more from me, check my links:
|
||||||
|
|
||||||
- [GitHub](https://github.com/sillydan1)
|
- [GitHub](https://github.com/sillydan1)
|
||||||
|
@ -21,20 +21,29 @@ management and interaction with the terminal both during the setup process and d
|
|||||||
|
|
||||||
## Server
|
## Server
|
||||||
|
|
||||||
The very first thing to get is a server. This can either be the machine you're currently using if you don't want to mess
|
The very first thing to get is a server. This can either be the machine you're currently using if you don't want
|
||||||
around on the public internet, or it could be an actual desktop you have set up with a public IP. Or it could be a VPS
|
to mess around on the public internet, or it could be an actual desktop you have set up with a public IP. Or
|
||||||
(Virtual Private Server) - which is just a fancy word for a "cloud computer" that someone else hosts and powers, and you
|
it could be a VPS (Virtual Private Server) - which is just a fancy word for a "cloud computer" that someone
|
||||||
just get an SSH connection to it. Any VPS provider will work, but [digital ocean](https://www.digitalocean.com/) is very
|
else hosts and powers, and you just get an SSH connection to it. Any VPS provider will work, but [digital
|
||||||
affordable and easy to use. As long as you get a VPS and avoid a *webhotel*, you should be fine (side note: webhotels
|
ocean](https://www.digitalocean.com/) or [linode](https://www.linode.com/) are very affordable and easy to use
|
||||||
are a scam and you shouldn't ever use them - especially not if you're tech-savvy enough to read this blog).
|
VPS providers. As long as you get a VPS and avoid a *webhotel*, you should be fine (side note: web hotels are a
|
||||||
|
scam and you shouldn't ever use them - especially not if you're tech-savvy enough to read this blog).
|
||||||
|
|
||||||
Once you have your server, [install](https://docs.docker.com/engine/install/) docker on it. Preferably the latest
|
Once you have your server, [install](https://docs.docker.com/engine/install/) docker on it. Preferably the latest
|
||||||
version.
|
version.
|
||||||
|
|
||||||
## Traefik and Portainer
|
## Traefik and Portainer
|
||||||
|
|
||||||
The very first thing to get done is set up portainer and traefik. This is done by creating a new `docker-compose.yml`
|
Traefik is a load balancer / application proxy that makes it easy for you to route network traffic into your various
|
||||||
file on your server. Just to keep things tidy, you should make a directory for all you are going to do here.
|
services on your server. By using traefik, you can have multiple docker containers, each providing their own service on
|
||||||
|
a single server, and traefik just routes user traffic based on the URL request, or ports used.
|
||||||
|
|
||||||
|
Portainer is a web-based docker container management GUI (Graphical User Interface) - if you've tried Docker Desktop,
|
||||||
|
think if portainer as a web-based version of that.
|
||||||
|
|
||||||
|
Getting traefik and portainer up and runinng is done by creating a new `docker-compose.yml` file on your server
|
||||||
|
and adding them as individual services. Just to keep things tidy, you should make a directory for all you are
|
||||||
|
going to do here. Do the following on your server.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
# Make the config directory in your $HOME dir - this is where
|
# Make the config directory in your $HOME dir - this is where
|
||||||
@ -49,15 +58,16 @@ cd ~/config
|
|||||||
touch docker-compose.yml
|
touch docker-compose.yml
|
||||||
```
|
```
|
||||||
|
|
||||||
It might be a good idea to initialize the `control` directory as a (local) `git` project. That way you will always have
|
It might be a good idea to initialize the `config` directory as a (local) `git` project. That way you will always have
|
||||||
a history of what you have been done, and what you did when you (inevitably) break things. This I will leave up to you
|
a history of what you have been done, and what you did when you (inevitably) break things. This I will leave up to you
|
||||||
though (probably gitignore the `portainer-data` directory).
|
though (you should gitignore the `portainer-data` directory, since that's managed by portainer and may contain a bunch
|
||||||
|
of stuff you don't want).
|
||||||
|
|
||||||
Inside the new `docker-compose.yml` file, you should put the following content (open the file using your favorite
|
Inside the new `docker-compose.yml` file, you should put the following content. Simply open the file using your favorite
|
||||||
terminal text editor).
|
terminal text editor and paste the following. Note! Don't start the stack yet - we still need to configure a bunch of
|
||||||
|
things.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
# docker-compose.yml
|
|
||||||
services:
|
services:
|
||||||
traefik:
|
traefik:
|
||||||
image: traefik:latest
|
image: traefik:latest
|
||||||
@ -84,6 +94,9 @@ services:
|
|||||||
- traefik.http.routers.traefik-secure.service=traefik
|
- traefik.http.routers.traefik-secure.service=traefik
|
||||||
- traefik.http.routers.traefik-secure.middlewares=user-auth@file
|
- traefik.http.routers.traefik-secure.middlewares=user-auth@file
|
||||||
- traefik.http.routers.traefik-secure.service=api@internal
|
- traefik.http.routers.traefik-secure.service=api@internal
|
||||||
|
environment:
|
||||||
|
- "CF_DNS_API_TOKEN=" # ADD YOUR OWN DNS API TOKEN HERE
|
||||||
|
- "CF_ZONE_API_TOKEN=" # ADD YOUR OWN DNS API TOKEN HERE
|
||||||
|
|
||||||
portainer:
|
portainer:
|
||||||
image: portainer/portainer-ce:alpine
|
image: portainer/portainer-ce:alpine
|
||||||
@ -115,25 +128,145 @@ are common to both of them, we set the initial niceties, such as the `container_
|
|||||||
and set their shared network to be the externally defined `proxy` network. Both services need (read-only) access to the
|
and set their shared network to be the externally defined `proxy` network. Both services need (read-only) access to the
|
||||||
system time for various reasons, so we volume mount `/etc/localtime` to their respective internal `/etc/localtime`. They
|
system time for various reasons, so we volume mount `/etc/localtime` to their respective internal `/etc/localtime`. They
|
||||||
also both need access to the system docker socket, so we also volume mount that in (again, read-only). Then we map the
|
also both need access to the system docker socket, so we also volume mount that in (again, read-only). Then we map the
|
||||||
various configuration files in (we will soon make these).
|
various configuration directories to their respective services.
|
||||||
|
|
||||||
If you haven't used `traefik` before, you might be scratching your head on the `labels` that we set on each of the
|
If you haven't used `traefik` before, you might be scratching your head on the `labels` that we set on each of the
|
||||||
services. This is how you configure services to integrate into traefik, enabling you to route your various containers to
|
services. This is just how you configure services to integrate into traefik, enabling you to route your various
|
||||||
various subdomains, integrate middlewares such as forcing HTTPS and setting load-balancer settings etc.
|
containers to various subdomains, integrate middle-wares such as forcing HTTPS and setting load-balancer settings etc.
|
||||||
|
|
||||||
Let's add the configuration files, shall we?
|
The `CF_DNS_API_TOKEN` and `CF_ZONE_API_TOKEN` tokens are our cloudflare API keys. If you're using a different DNS
|
||||||
|
provider, you should check the [traefik documentation](https://doc.traefik.io/traefik/https/acme/#providers) to see if
|
||||||
|
your provider is supported, and change the environment variable names accordingly.
|
||||||
|
|
||||||
## Keycloak
|
Since the configuration directories are currently empty, the setup won't work yet. Let's add the traefik configuration
|
||||||
|
files first:
|
||||||
|
|
||||||
## TODOs
|
```sh
|
||||||
- [ ] 2FA the control dashboards through keycloak
|
cd ~/config/traefik-data
|
||||||
- [x] geoblocking the control dashboards
|
mkdir -p configurations
|
||||||
- [ ] start the article with a demo of what we'll be making
|
touch traefik.yml
|
||||||
- MAYBE:
|
touch configurations/dynamic.yml
|
||||||
- [ ] portainer introduction (maybe)
|
```
|
||||||
- [ ] traefik introduction (maybe)
|
|
||||||
- [ ] add a "skip if you already know portainer and traefik"
|
|
||||||
|
|
||||||
|
The `traefik.yml` file contains your general traefik configuration. This is where you register certificates, enforce
|
||||||
|
HTTPS and set general settings. The content we're interested in having is the following:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
api:
|
||||||
|
dashboard: true
|
||||||
|
|
||||||
|
entryPoints:
|
||||||
|
web:
|
||||||
|
address: ":80"
|
||||||
|
http:
|
||||||
|
redirections:
|
||||||
|
entryPoint:
|
||||||
|
to: websecure
|
||||||
|
websecure:
|
||||||
|
address: ":443"
|
||||||
|
http:
|
||||||
|
middlewares:
|
||||||
|
- secureHeaders@file
|
||||||
|
tls:
|
||||||
|
certResolver: letsencrypt
|
||||||
|
|
||||||
|
certificatesResolvers:
|
||||||
|
letsencrypt:
|
||||||
|
acme:
|
||||||
|
email: your-email-here
|
||||||
|
storage: acme.json
|
||||||
|
keyType: EC384
|
||||||
|
dnsChallenge:
|
||||||
|
provider: cloudflare
|
||||||
|
delayBeforeCheck: 0
|
||||||
|
|
||||||
|
providers:
|
||||||
|
docker:
|
||||||
|
endpoint: "unix:///var/run/docker.sock"
|
||||||
|
exposedByDefault: false
|
||||||
|
file:
|
||||||
|
filename: /configurations/dynamic.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
The first `api` section is pretty self-explanatory enables the web-ui dashboard. You can choose not to do
|
||||||
|
this if you don't want the traefik web dashboard. The `entryPoints` section is a bit more interesting. This
|
||||||
|
is where we enforce that all HTTP web-requests on port `80` will be redirected to port `443` using transport
|
||||||
|
layer security (TLS). You might notice that we specifically mention `letsencrypt` here, this leads us
|
||||||
|
to the `certificatesResolvers` section. Since I am using [cloudflare](https://www.cloudflare.com/)
|
||||||
|
as my DNS (Domain Name Service) provider, I can also use them as my TLS certificate provider as
|
||||||
|
they provide this service. This is a complex topic and if you're interested, I recommend reading
|
||||||
|
[this](https://blog.cloudflare.com/introducing-automatic-ssl-tls-securing-and-simplifying-origin-connectivity/)
|
||||||
|
blog post by cloudflare themselves. Boiling all this jargan down, we are just using cloudflare as a middleman to
|
||||||
|
help us get the little lock icon in the browser when someone visits our website(s). I've set the certificates to
|
||||||
|
automatically update, so I don't have to worry about it ever again.
|
||||||
|
|
||||||
|
The `providers` settings refer to where traefik can route internet traffic to. We simply register `docker` as a service
|
||||||
|
provider as well as the configurations we define in `configurations/dynamic.yml`. Let's take a look at the content of
|
||||||
|
that file.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
http:
|
||||||
|
middlewares:
|
||||||
|
secureHeaders:
|
||||||
|
headers:
|
||||||
|
sslRedirect: true
|
||||||
|
forceSTSHeader: true
|
||||||
|
stsIncludeSubdomains: true
|
||||||
|
stsPreload: true
|
||||||
|
stsSeconds: 31536000
|
||||||
|
user-auth:
|
||||||
|
basicAuth:
|
||||||
|
users:
|
||||||
|
- "administrator:<password>" # ADD YOUR ADMIN PASSWORD HERE ()
|
||||||
|
|
||||||
|
tls:
|
||||||
|
options:
|
||||||
|
default:
|
||||||
|
cipherSuites:
|
||||||
|
- TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
|
||||||
|
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
|
||||||
|
- TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
|
||||||
|
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
|
||||||
|
- TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305
|
||||||
|
- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
|
||||||
|
minVersion: VersionTLS12
|
||||||
|
```
|
||||||
|
|
||||||
|
Starting in the `http.middlewares` section, we first register a TLS middleware that we call `secureHeaders` (note that
|
||||||
|
this is the middleware referred in `traefik.yml`) - skipping past the details, this middleware simply adds security
|
||||||
|
headers to each request. Our second middleware, `user-auth` is the authentication method to gain access to the traefik
|
||||||
|
dashboard. Here we set the username `username` and you should generate the password using the `htpasswd` command. This
|
||||||
|
command should be available through the `apache2-utils` package on ubuntu systems, and `extra/apache` on Arch. Simply
|
||||||
|
copy / paste the generated hashed password into your yaml file.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# -n = output to stdout -B = use bcrypt
|
||||||
|
# Make sure to replace 'administrator' if you want a different username
|
||||||
|
htpasswd -nB administrator
|
||||||
|
```
|
||||||
|
|
||||||
|
## Starting Everything
|
||||||
|
|
||||||
|
We should now have everything set up and ready for starting! Simply navigate to the `~/control` directory and start the
|
||||||
|
docker compose stack.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# Start the containers (detached)
|
||||||
|
docker compose up -d
|
||||||
|
|
||||||
|
# Follow along with the logs
|
||||||
|
docker compose logs -f
|
||||||
|
```
|
||||||
|
|
||||||
|
Hopefully there shouldn't be any errors, but if there are, make doubly sure that your TLS settings are set correctly,
|
||||||
|
as that's likely to be the thing to mess up (ask me how I know). If you need additional assistance, the [official
|
||||||
|
traefik docs](https://doc.traefik.io/traefik/) are a great resource. Portainer is fairly fool-proof, so I don't expect
|
||||||
|
that to cause you any problems.
|
||||||
|
|
||||||
|
## TODO
|
||||||
|
- [ ] DNS records, ACME challenges, TXT records, Wildcard A records, CAA records - jesus there's so much shit I've forgotten
|
||||||
|
|
||||||
|
{{< centered image="/6616144.png" >}}
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
services:
|
services:
|
||||||
@ -181,5 +314,3 @@ networks:
|
|||||||
external: true
|
external: true
|
||||||
keycloak:
|
keycloak:
|
||||||
```
|
```
|
||||||
|
|
||||||
{{< centered image="/6616144.png" >}}
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user