Compare commits
18 Commits
8fa5b7c57b
...
main
Author | SHA1 | Date | |
---|---|---|---|
a05fcb8ade
|
|||
6313bc5ec7
|
|||
21abbe97ed
|
|||
6582a72b43
|
|||
86085039ff
|
|||
beb4088c51
|
|||
9f40e247b9
|
|||
a46b00bd07
|
|||
90587ed5d1
|
|||
3f6b504dfc
|
|||
0db871b63f
|
|||
55eb86ff0c
|
|||
ed099f6f1a | |||
30e207a87c | |||
7b881e5da1 | |||
69b2ddf40b
|
|||
f13cdaff60
|
|||
4915eac171
|
1
.gitignore
vendored
1
.gitignore
vendored
@@ -2,3 +2,4 @@
|
|||||||
/config/traefik/dynamic/*
|
/config/traefik/dynamic/*
|
||||||
!/config/traefik/dynamic/ssl.yaml
|
!/config/traefik/dynamic/ssl.yaml
|
||||||
!/config/traefik/dynamic/dashboard.yaml
|
!/config/traefik/dynamic/dashboard.yaml
|
||||||
|
services/
|
||||||
|
90
README.md
90
README.md
@@ -2,7 +2,7 @@
|
|||||||
<img src="https://git.max-richter.dev/attachments/3cea8ffa-57cc-4faf-a973-7a3b34a012e0" width="30%"/>
|
<img src="https://git.max-richter.dev/attachments/3cea8ffa-57cc-4faf-a973-7a3b34a012e0" width="30%"/>
|
||||||
<h2 align="center">LocalCerts</h2>
|
<h2 align="center">LocalCerts</h2>
|
||||||
<p align="center">
|
<p align="center">
|
||||||
Automatic HTTPS and local domain routing for Docker Compose services using Traefik and Step-CA.
|
Automatic HTTPS and local domain routing for Docker Compose services using <a href="https://github.com/traefik/traefik">Traefik</a>, <a href="https://github.com/mageddo/dns-proxy-server">DPS</a> and <a href="https://github.com/smallstep/certificates">Step-CA</a>.
|
||||||
</p>
|
</p>
|
||||||
<p align="center">
|
<p align="center">
|
||||||
Created by <a href="https://github.com/Sajito">@Sajito</a>
|
Created by <a href="https://github.com/Sajito">@Sajito</a>
|
||||||
@@ -15,15 +15,28 @@
|
|||||||
1. Clone this repository and navigate into the directory.
|
1. Clone this repository and navigate into the directory.
|
||||||
|
|
||||||
2. Start the services:
|
2. Start the services:
|
||||||
```bash
|
```shell
|
||||||
docker compose up -d
|
docker compose up -d
|
||||||
```
|
```
|
||||||
|
|
||||||
3. Trust the Step-CA root certificate:
|
3. Trust the Step-CA root certificate:
|
||||||
```bash
|
|
||||||
curl -k https://localhost:9000/roots.pem -o roots.pem
|
Download the `roots.pem` from [https://localhost:9000/roots.pem](https://localhost:9000/roots.pem) and trust it on your system.
|
||||||
|
This is necessary for the certificates to be trusted by your browser.
|
||||||
|
|
||||||
|
- Linux
|
||||||
|
```shell
|
||||||
sudo trust anchor --store roots.pem
|
sudo trust anchor --store roots.pem
|
||||||
rm roots.pem
|
```
|
||||||
|
|
||||||
|
- Windows
|
||||||
|
```powershell
|
||||||
|
Import-Certificate -FilePath "roots.pem" -CertStoreLocation "Cert:\LocalMachine\Root"
|
||||||
|
```
|
||||||
|
|
||||||
|
- macOS
|
||||||
|
```shell
|
||||||
|
sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain roots.pem
|
||||||
```
|
```
|
||||||
|
|
||||||
## How to Use
|
## How to Use
|
||||||
@@ -49,7 +62,7 @@ labels:
|
|||||||
> For each overwritten port you need to specify a custom `service-label` `traefik.http.services.[service-label]`. Otherwise the custom port will not be detected.
|
> For each overwritten port you need to specify a custom `service-label` `traefik.http.services.[service-label]`. Otherwise the custom port will not be detected.
|
||||||
|
|
||||||
- If certificates are not renewed or have expired
|
- If certificates are not renewed or have expired
|
||||||
```bash
|
```shell
|
||||||
docker compose up -d --force-recreate traefik
|
docker compose up -d --force-recreate traefik
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -60,62 +73,67 @@ docker compose up -d --force-recreate traefik
|
|||||||
For example `dev.cool` 😎
|
For example `dev.cool` 😎
|
||||||
|
|
||||||
Replace `.dev.local` with your custom domain suffix in the `config/traefik/traefik.yml` file:
|
Replace `.dev.local` with your custom domain suffix in the `config/traefik/traefik.yml` file:
|
||||||
```yaml
|
```diff
|
||||||
...
|
docker:
|
||||||
docker:
|
defaultRule: |
|
||||||
defaultRule: |
|
- Host(`{{ trim (index .Labels "serviceName") }}.dev.local`) {{range $i, $domain := splitList "," (index .Labels "serviceDomains")}}{{if ne $domain ""}}|| Host(`{{$domain}}`){{end}}{{end}}
|
||||||
Host(`{{ trim (index .Labels "serviceName") }}.dev.cool`) {{range $i, $domain := splitList "," (index .Labels "serviceDomains")}}{{if ne $domain ""}}|| Host(`{{$domain}}`){{end}}{{end}}
|
+ Host(`{{ trim (index .Labels "serviceName") }}.dev.cool`) {{range $i, $domain := splitList "," (index .Labels "serviceDomains")}}{{if ne $domain ""}}|| Host(`{{$domain}}`){{end}}{{end}}
|
||||||
...
|
constraints: LabelRegex(`serviceName`, `.+`) && !Label(`com.docker.compose.oneoff`, `True`)
|
||||||
```
|
```
|
||||||
|
|
||||||
Replace `.dev.local` with your custom domain suffix in the `config/dns/config.sample.json` file:
|
Replace `.dev.local` with your custom domain suffix in the `config/dns/config.sample.json` file:
|
||||||
```json
|
```diff
|
||||||
...
|
{
|
||||||
{
|
"id": 2,
|
||||||
"id": 2,
|
- "hostname": ".dev.local",
|
||||||
"hostname": ".dev.cool",
|
+ "hostname": ".dev.cool",
|
||||||
"ip": "",
|
"ip": "",
|
||||||
"target": "host.docker",
|
|
||||||
"ttl": 3600,
|
|
||||||
"type": "CNAME"
|
|
||||||
}
|
|
||||||
...
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Remove the dns_config volume
|
Restart the docker services to apply the changes:
|
||||||
```bash
|
```shell
|
||||||
docker compose down
|
docker compose up -d --force-recreate
|
||||||
docker compose volukme rm dns_config
|
|
||||||
docker compose up -d
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Custom Domain Per Service
|
||||||
|
|
||||||
|
If you want a single service to have a custom domain you can use the `serviceDomains` label. This will override the default domain suffix:
|
||||||
|
```yaml
|
||||||
|
labels:
|
||||||
|
serviceName: my-app
|
||||||
|
serviceDomains: my-app.very.cool
|
||||||
|
```
|
||||||
|
|
||||||
|
The service would now be reachable at `https://my-app.very.cool` and `https://my-app.dev.local`.
|
||||||
|
|
||||||
### Certificate Lifetime
|
### Certificate Lifetime
|
||||||
|
|
||||||
To ensure Traefik has enough time to renew certificates, increase their duration:
|
To ensure Traefik has enough time to renew certificates, increase their duration:
|
||||||
```bash
|
```shell
|
||||||
docker compose exec step step ca provisioner update acme \
|
docker compose exec step step ca provisioner update acme \
|
||||||
--x509-min-dur=20m \
|
--x509-min-dur=20m \
|
||||||
--x509-max-dur=8760h \
|
--x509-max-dur=8760h \
|
||||||
--x509-default-dur=2160h
|
--x509-default-dur=2160h
|
||||||
```
|
```
|
||||||
|
|
||||||
### Use the preconfigured services
|
### Create a shell script to start/stop general services
|
||||||
|
|
||||||
If you use the preconfigured services, you can add the following snippet to you `.bashrc/.zshrc` to easily start, stop, and manage the services.
|
I often use tools like dbgate to interact with databases. For such utilities, I maintain a services/compose.yml file in this directory, where each service is defined with a custom profile. This setup allows me to start and stop individual services as needed.
|
||||||
|
|
||||||
```bash
|
If you use the preconfigured services, you can add the following snippet to you `.bashrc`/`.zshrc` to easily start, stop, and manage the services. Make sure to update the `PROJECT_DIR` variable to point to the correct directory.
|
||||||
|
|
||||||
|
```shell
|
||||||
dev () {
|
dev () {
|
||||||
PROJECT_DIR="$HOME/Projects/dev/services"
|
PROJECT_DIR="$HOME/Projects/dev/services"
|
||||||
case "$1" in
|
case "$1" in
|
||||||
(start) shift
|
(start) shift
|
||||||
docker compose -f "$PROJECT_DIR/docker-compose.yml" --profile "$@" up -d ;;
|
docker compose -f "$PROJECT_DIR/compose.yml" --profile "$@" up -d ;;
|
||||||
(restart) shift
|
(restart) shift
|
||||||
docker compose -f "$PROJECT_DIR/docker-compose.yml" --profile "$@" restart ;;
|
docker compose -f "$PROJECT_DIR/compose.yml" --profile "$@" restart ;;
|
||||||
(stop) shift
|
(stop) shift
|
||||||
docker compose -f "$PROJECT_DIR/docker-compose.yml" --profile "$@" down --remove-orphans ;;
|
docker compose -f "$PROJECT_DIR/compose.yml" --profile "$@" down --remove-orphans ;;
|
||||||
(logs) shift
|
(logs) shift
|
||||||
docker compose -f "$PROJECT_DIR/docker-compose.yml" --profile "$@" logs -f ;;
|
docker compose -f "$PROJECT_DIR/compose.yml" --profile "$@" logs -f ;;
|
||||||
(*) echo "Usage: dev {start|restart|stop|logs} [services...]" ;;
|
(*) echo "Usage: dev {start|restart|stop|logs} [services...]" ;;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
6
compose.override.example.yml
Normal file
6
compose.override.example.yml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
services:
|
||||||
|
dns:
|
||||||
|
volumes:
|
||||||
|
- /etc:/host/etc
|
||||||
|
environment:
|
||||||
|
MG_RESOLVCONF: /host/etc/resolv.conf
|
@@ -19,7 +19,7 @@ services:
|
|||||||
ipv4_address: 172.157.5.249
|
ipv4_address: 172.157.5.249
|
||||||
|
|
||||||
traefik:
|
traefik:
|
||||||
image: traefik:3.3
|
image: traefik:3.4.1
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
volumes:
|
volumes:
|
||||||
- /var/run/docker.sock:/var/run/docker.sock
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
@@ -38,4 +38,4 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
}
|
||||||
|
0
services/.gitignore
vendored
0
services/.gitignore
vendored
@@ -1,67 +0,0 @@
|
|||||||
services:
|
|
||||||
mailpit:
|
|
||||||
profiles:
|
|
||||||
- mail
|
|
||||||
image: axllent/mailpit
|
|
||||||
ports:
|
|
||||||
- 1025:1025
|
|
||||||
environment:
|
|
||||||
MP_UI_BIND_ADDR: "0.0.0.0:8085"
|
|
||||||
labels:
|
|
||||||
serviceName: mail
|
|
||||||
traefik.http.services.mail.loadbalancer.server.port: 8085
|
|
||||||
|
|
||||||
datasette:
|
|
||||||
ports:
|
|
||||||
- 8001:8001
|
|
||||||
volumes:
|
|
||||||
- datasette:/mnt
|
|
||||||
image: datasetteproject/datasette
|
|
||||||
command: datasette -p 8001 -h 0.0.0.0 --plugins-dir=/mnt/plugins/ --config default_page_size:500 /mnt/data/qs-monitor-usage.db
|
|
||||||
profiles:
|
|
||||||
- data
|
|
||||||
labels:
|
|
||||||
serviceName: data
|
|
||||||
traefik.http.services.data.loadbalancer.server.port: 8001
|
|
||||||
|
|
||||||
silverbullet:
|
|
||||||
profiles:
|
|
||||||
- notes
|
|
||||||
image: ghcr.io/silverbulletmd/silverbullet:v2
|
|
||||||
volumes:
|
|
||||||
- ~/Notes:/space
|
|
||||||
labels:
|
|
||||||
serviceName: notes
|
|
||||||
|
|
||||||
db:
|
|
||||||
profiles:
|
|
||||||
- db
|
|
||||||
build: docker
|
|
||||||
image: dbgate/dbgate:beta-alpine
|
|
||||||
labels:
|
|
||||||
serviceName: db
|
|
||||||
volumes:
|
|
||||||
- dbgate:/root/.dbgate
|
|
||||||
|
|
||||||
grafana:
|
|
||||||
profiles:
|
|
||||||
- logs
|
|
||||||
image: grafana/grafana:11.2.0
|
|
||||||
environment:
|
|
||||||
- GF_AUTH_ANONYMOUS_ORG_ROLE=Admin
|
|
||||||
- GF_AUTH_ANONYMOUS_ENABLED=true
|
|
||||||
- GF_AUTH_BASIC_ENABLED=false
|
|
||||||
- GF_FEATURE_TOGGLES_ENABLE=accessControlOnCall lokiLogsDataplane exploreLogsShardSplitting
|
|
||||||
- GF_PLUGINS_PREINSTALL_DISABLED=true
|
|
||||||
- GF_INSTALL_PLUGINS=https://storage.googleapis.com/integration-artifacts/grafana-lokiexplore-app/grafana-lokiexplore-app-latest.zip;grafana-lokiexplore-app
|
|
||||||
labels:
|
|
||||||
serviceName: grafana
|
|
||||||
volumes:
|
|
||||||
- ./provisioning/grafana:/etc/grafana/provisioning
|
|
||||||
extra_hosts:
|
|
||||||
- 'host.docker.internal:host-gateway'
|
|
||||||
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
dbgate: ~
|
|
||||||
datasette: ~
|
|
@@ -1,8 +0,0 @@
|
|||||||
apiVersion: 1
|
|
||||||
|
|
||||||
datasources:
|
|
||||||
- name: gdev-loki
|
|
||||||
type: loki
|
|
||||||
uid: gdev-loki
|
|
||||||
access: proxy
|
|
||||||
url: http://host.docker.internal:3100
|
|
@@ -1,12 +0,0 @@
|
|||||||
apiVersion: 1
|
|
||||||
|
|
||||||
apps:
|
|
||||||
- type: "grafana-lokiexplore-app"
|
|
||||||
org_id: 1
|
|
||||||
org_name: "Grafana"
|
|
||||||
disabled: false
|
|
||||||
jsonData:
|
|
||||||
apiUrl: http://default-url.com
|
|
||||||
isApiKeySet: true
|
|
||||||
secureJsonData:
|
|
||||||
apiKey: secret-key
|
|
Reference in New Issue
Block a user