Compare commits
20 commits
Author | SHA1 | Date | |
---|---|---|---|
a57d59ac04 | |||
c25e4ca41d | |||
8a634be9ab | |||
37fe3937e5 | |||
e6f64d4f4d | |||
2cc35feebb | |||
bf094a02d6 | |||
69cf0a1d4b | |||
72d07aac36 | |||
aa0987593e | |||
58aeaacc67 | |||
fef821f770 | |||
cd224321df | |||
b8adaee9d4 | |||
723bc7ed33 | |||
9eb52229f1 | |||
b89713643d | |||
f8bd422451 | |||
7c220a5501 | |||
74a4de1615 |
105 changed files with 354 additions and 408 deletions
64
README.md
64
README.md
|
@ -1,69 +1,23 @@
|
||||||
# Max
|
# Max
|
||||||
|
|
||||||
This repository contains Ansible scripts to setup our main home server `max`.
|
Max is our VM running all of our web servers, provisioned with Terraform and configured with Ansible.
|
||||||
The `common` role executes some common OS tasks.
|
|
||||||
The `docker` role installs Docker.
|
|
||||||
The other roles are specifically for the various services we run.
|
|
||||||
|
|
||||||
## Running services
|
## Running services
|
||||||
|
|
||||||
All services below are running under Docker, except NSD and Borg.
|
All services below are implemented using Docker:
|
||||||
|
|
||||||
- Reverse proxy using [Traefik](https://doc.traefik.io/traefik/)
|
- Reverse proxy using [Traefik](https://doc.traefik.io/traefik/)
|
||||||
- Git server using [Forgejo](https://forgejo.org/) ([git.pizzapim.nl](https://git.pizzapim.nl))
|
- Git server using [Forgejo](https://forgejo.org/) ([git.pim.kunis.nl](https://git.pim.kunis.nl))
|
||||||
- Static website using [Jekyll](https://jekyllrb.com/) ([pizzapim.nl](https://pizzapim.nl))
|
- Static website using [Jekyll](https://jekyllrb.com/) ([pim.kunis.nl](https://pim.kunis.nl))
|
||||||
- File sychronisation using [Syncthing](https://syncthing.net/)
|
- File sychronisation using [Syncthing](https://syncthing.net/)
|
||||||
- Microblogging server using [Mastodon](https://joinmastodon.org/) ([social.pizzapim.nl](https://social.pizzapim.nl))
|
- Microblogging server using [Mastodon](https://joinmastodon.org/) ([social.pizzapim.nl](https://social.pizzapim.nl))
|
||||||
- Calendar and contact synchronisation using [Radicale](https://radicale.org/v3.html) ([dav.pizzapim.nl](https://dav.pizzapim.nl))
|
- Calendar and contact synchronisation using [Radicale](https://radicale.org/v3.html) ([dav.pim.kunis.nl](https://dav.pim.kunis.nl))
|
||||||
- KMS server using [vlmcsd](https://github.com/Wind4/vlmcsd)
|
- KMS server using [vlmcsd](https://github.com/Wind4/vlmcsd)
|
||||||
- Cloud file storage using [Seafile](https://www.seafile.com)
|
- Cloud file storage using [Seafile](https://www.seafile.com)
|
||||||
- Inbucket disposable webmail, Mailinator alternative (https://inbucket.org)
|
- Disposable mail server using [Inbucket](https://inbucket.org)
|
||||||
- Cyberchef (https://cyberchef.geokunis2.nl)
|
- Digital toolbox using [Cyberchef](https://cyberchef.geokunis2.nl)
|
||||||
- Jitsi Meet (https://meet.jit.si)
|
- Jitsi Meet (https://meet.jit.si)
|
||||||
- RSS feed reader using [FreshRSS](https://miniflux.app/)
|
- RSS feed reader using [FreshRSS](https://miniflux.app/)
|
||||||
- Metrics using [Prometheus](https://prometheus.io/)
|
- Metrics using [Prometheus](https://prometheus.io/)
|
||||||
|
- Latex editor using [Overleaf](https://www.overleaf.com/) ([latex.pim.kunis.nl](https://latex.pim.kunis.nl))
|
||||||
## Virtualization
|
- Markdown editor using [Hedgedoc](https://hedgedoc.org/)
|
||||||
|
|
||||||
Currently this repository is ran as a physical server, but we intend to virtualize it.
|
|
||||||
First, the whole server should be virtualized on a single virtual machine.
|
|
||||||
After that, it will be split up into several virtual machines.
|
|
||||||
The services on each virtual machine should have similar services/security properties.
|
|
||||||
|
|
||||||
Provisional split of services on virtual machines:
|
|
||||||
- "public web" VM: Mastodon, static HTML server, cyberchef, jitsi meet, inbucket
|
|
||||||
- "data" VM: seafile, radicale, syncthing, freshrss
|
|
||||||
- "management" VM: reverse proxy, prometheus, kms
|
|
||||||
- "git" VM: forgejo. Because forgejo is a somewhat single point of failure, it should have its own VM.
|
|
||||||
|
|
||||||
## Possible future services
|
|
||||||
|
|
||||||
- matrix
|
|
||||||
- peertube?
|
|
||||||
- Pixelfed?
|
|
||||||
- Prometheus
|
|
||||||
- Concourse CI?
|
|
||||||
|
|
||||||
## TODO
|
|
||||||
|
|
||||||
- Clear view of what services + which versions we are running. This way, we can track security updates better.
|
|
||||||
- Host tobb website?
|
|
||||||
- Move from Ubuntu to Debian
|
|
||||||
- move Mastodon to pim.kunis.nl
|
|
||||||
- Podman
|
|
||||||
- Replace watchtower with Podman features
|
|
||||||
|
|
||||||
### NSD
|
|
||||||
|
|
||||||
#### ZSK Rollover
|
|
||||||
|
|
||||||
Could make automatic key rollovers with cron or some other tool.
|
|
||||||
|
|
||||||
#### Idempotency
|
|
||||||
|
|
||||||
Currently I always resign zones.
|
|
||||||
But for idempotency I should probably only do it if the zone has changed or the keys have changed.
|
|
||||||
|
|
||||||
### Firewall
|
|
||||||
|
|
||||||
A little more difficult because of docker networking but probably doable.
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
base_data_dir: /mnt/data
|
base_data_dir: /mnt/data
|
||||||
base_service_dir: /srv
|
base_service_dir: /srv
|
||||||
|
domain_name_pim: pim.kunis.nl
|
||||||
|
|
||||||
# Additional open ports
|
# Additional open ports
|
||||||
jitsi_videobridge_port: 54562
|
jitsi_videobridge_port: 54562
|
||||||
|
@ -8,4 +9,7 @@ prometheus_port: 8081
|
||||||
traefik_api_port: 8080
|
traefik_api_port: 8080
|
||||||
internal_forgejo_port: 3000 # Needed to pull from a repository from another docker container.
|
internal_forgejo_port: 3000 # Needed to pull from a repository from another docker container.
|
||||||
|
|
||||||
domain_name_pim: pim.kunis.nl
|
docker_daemon_config:
|
||||||
|
default-address-pools:
|
||||||
|
- base: "10.204.0.0/16"
|
||||||
|
size: 24
|
|
@ -2,4 +2,4 @@ all:
|
||||||
hosts:
|
hosts:
|
||||||
max:
|
max:
|
||||||
ansible_user: root
|
ansible_user: root
|
||||||
ansible_host: max2.dmz
|
ansible_host: max.dmz
|
36
ansible/max.yml
Normal file
36
ansible/max.yml
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
- name: Wait for servers to come up
|
||||||
|
hosts: max
|
||||||
|
gather_facts: no
|
||||||
|
roles:
|
||||||
|
- 'cloudinit-wait'
|
||||||
|
|
||||||
|
- name: Start services
|
||||||
|
hosts: max
|
||||||
|
pre_tasks:
|
||||||
|
- name: Create base service directory
|
||||||
|
file:
|
||||||
|
path: "{{ base_service_dir }}"
|
||||||
|
state: directory
|
||||||
|
- name: Delete externally managed environment file
|
||||||
|
shell:
|
||||||
|
cmd: "rm /usr/lib/python*/EXTERNALLY-MANAGED"
|
||||||
|
register: rm
|
||||||
|
changed_when: "rm.rc == 0"
|
||||||
|
failed_when: "false"
|
||||||
|
roles:
|
||||||
|
- {role: 'setup-apt', tags: 'setup-apt'}
|
||||||
|
- {role: 'watchtower', tags: 'watchtower'}
|
||||||
|
- {role: 'forgejo', tags: 'forgejo'}
|
||||||
|
- {role: 'syncthing', tags: 'syncthing'}
|
||||||
|
- {role: 'kms', tags: 'kms'}
|
||||||
|
- {role: 'cyberchef', tags: 'cyberchef'}
|
||||||
|
- {role: 'radicale', tags: 'radicale'}
|
||||||
|
- {role: 'mastodon', tags: 'mastodon'}
|
||||||
|
- {role: 'seafile', tags: 'seafile'}
|
||||||
|
- {role: 'jitsi', tags: 'jitsi'}
|
||||||
|
- {role: 'freshrss', tags: 'freshrss'}
|
||||||
|
- {role: 'static', tags: 'static'}
|
||||||
|
- {role: 'inbucket', tags: 'inbucket'}
|
||||||
|
- {role: 'prometheus', tags: 'prometheus'}
|
||||||
|
- {role: 'overleaf', tags: 'overleaf'}
|
||||||
|
- {role: 'hedgedoc', tags: 'hedgedoc'}
|
9
ansible/requirements.yml
Normal file
9
ansible/requirements.yml
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
- name: setup-apt
|
||||||
|
src: https://github.com/sunscrapers/ansible-role-apt.git
|
||||||
|
scm: git
|
||||||
|
- name: cloudinit-wait
|
||||||
|
src: https://git.pim.kunis.nl/pim/ansible-role-cloudinit-wait
|
||||||
|
scm: git
|
||||||
|
- name: docker
|
||||||
|
src: https://git.pim.kunis.nl/pim/ansible-role-docker
|
||||||
|
scm: git
|
2
ansible/roles/cyberchef/meta/main.yml
Normal file
2
ansible/roles/cyberchef/meta/main.yml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
dependencies:
|
||||||
|
- role: traefik
|
|
@ -11,4 +11,3 @@
|
||||||
project_src: "{{ service_dir }}"
|
project_src: "{{ service_dir }}"
|
||||||
pull: true
|
pull: true
|
||||||
remove_orphans: true
|
remove_orphans: true
|
||||||
|
|
2
ansible/roles/forgejo/meta/main.yml
Normal file
2
ansible/roles/forgejo/meta/main.yml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
dependencies:
|
||||||
|
- role: traefik
|
|
@ -39,6 +39,7 @@ CHARSET = utf8
|
||||||
|
|
||||||
[indexer]
|
[indexer]
|
||||||
ISSUE_INDEXER_PATH = /data/gitea/indexers/issues.bleve
|
ISSUE_INDEXER_PATH = /data/gitea/indexers/issues.bleve
|
||||||
|
ISSUE_INDEXER_TYPE = db
|
||||||
|
|
||||||
[session]
|
[session]
|
||||||
PROVIDER_CONFIG = /data/gitea/sessions
|
PROVIDER_CONFIG = /data/gitea/sessions
|
|
@ -3,7 +3,6 @@ data_dir: "{{ base_data_dir }}/{{ service_name }}"
|
||||||
service_dir: "{{ base_service_dir }}/{{ service_name }}"
|
service_dir: "{{ base_service_dir }}/{{ service_name }}"
|
||||||
git_domain: "git.{{ domain_name_pim }}"
|
git_domain: "git.{{ domain_name_pim }}"
|
||||||
|
|
||||||
|
|
||||||
forgejo:
|
forgejo:
|
||||||
root_url: "https://{{ git_domain }}"
|
root_url: "https://{{ git_domain }}"
|
||||||
mailer_host: "smtp.tweak.nl"
|
mailer_host: "smtp.tweak.nl"
|
2
ansible/roles/freshrss/meta/main.yml
Normal file
2
ansible/roles/freshrss/meta/main.yml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
dependencies:
|
||||||
|
- role: traefik
|
|
@ -11,10 +11,8 @@ services:
|
||||||
options:
|
options:
|
||||||
max-size: 10m
|
max-size: 10m
|
||||||
volumes:
|
volumes:
|
||||||
# Recommended volume for FreshRSS persistent data such as configuration and SQLite databases
|
- {{ data_dir }}/data:/var/www/FreshRSS/data
|
||||||
- /data/freshrss/data:/var/www/FreshRSS/data
|
- {{ data_dir }}/extensions:/var/www/FreshRSS/extensions
|
||||||
# Optional volume for storing third-party extensions
|
|
||||||
- /data/freshrss/extensions:/var/www/FreshRSS/extensions
|
|
||||||
environment:
|
environment:
|
||||||
TZ: Europe/Amsterdam
|
TZ: Europe/Amsterdam
|
||||||
CRON_MIN: '2,32'
|
CRON_MIN: '2,32'
|
2
ansible/roles/hedgedoc/meta/main.yml
Normal file
2
ansible/roles/hedgedoc/meta/main.yml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
dependencies:
|
||||||
|
- role: traefik
|
22
ansible/roles/hedgedoc/tasks/main.yml
Normal file
22
ansible/roles/hedgedoc/tasks/main.yml
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
- name: Create service directory
|
||||||
|
file:
|
||||||
|
path: "{{ service_dir }}"
|
||||||
|
state: directory
|
||||||
|
- name: Copy Docker Compose script
|
||||||
|
template:
|
||||||
|
src: "{{ role_path }}/templates/docker-compose.yml.j2"
|
||||||
|
dest: "{{ service_dir }}/docker-compose.yml"
|
||||||
|
- name: Create data directory
|
||||||
|
file:
|
||||||
|
path: "{{ data_dir }}"
|
||||||
|
state: directory
|
||||||
|
- name: Create uploads directory
|
||||||
|
file:
|
||||||
|
path: "{{ data_dir }}/uploads"
|
||||||
|
state: directory
|
||||||
|
mode: 0777
|
||||||
|
- name: Start the Docker Compose
|
||||||
|
docker_compose:
|
||||||
|
project_src: "{{ service_dir }}"
|
||||||
|
pull: true
|
||||||
|
remove_orphans: true
|
51
ansible/roles/hedgedoc/templates/docker-compose.yml.j2
Normal file
51
ansible/roles/hedgedoc/templates/docker-compose.yml.j2
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
version: '3'
|
||||||
|
|
||||||
|
networks:
|
||||||
|
traefik:
|
||||||
|
external: true
|
||||||
|
internal:
|
||||||
|
external: false
|
||||||
|
|
||||||
|
services:
|
||||||
|
database:
|
||||||
|
image: postgres:13.4-alpine
|
||||||
|
container_name: hedgedoc-database
|
||||||
|
environment:
|
||||||
|
- POSTGRES_USER=hedgedoc
|
||||||
|
- POSTGRES_PASSWORD=password
|
||||||
|
- POSTGRES_DB=hedgedoc
|
||||||
|
volumes:
|
||||||
|
- {{ data_dir }}/database:/var/lib/postgresql/data
|
||||||
|
restart: always
|
||||||
|
networks:
|
||||||
|
- internal
|
||||||
|
|
||||||
|
app:
|
||||||
|
image: quay.io/hedgedoc/hedgedoc:1.9.7
|
||||||
|
container_name: hedgedoc
|
||||||
|
environment:
|
||||||
|
- CMD_DB_URL=postgres://hedgedoc:password@database:5432/hedgedoc
|
||||||
|
- CMD_DOMAIN={{ hedgedoc_domain }}
|
||||||
|
- CMD_PORT=3000
|
||||||
|
- CMD_URL_ADDPORT=false
|
||||||
|
- CMD_ALLOW_ANONYMOUS=true
|
||||||
|
- CMD_ALLOW_EMAIL_REGISTER=false
|
||||||
|
- CMD_PROTOCOL_USESSL=true
|
||||||
|
- CMD_SESSION_SECRET={{ session_secret }}
|
||||||
|
volumes:
|
||||||
|
- {{ data_dir }}/uploads:/hedgedoc/public/uploads
|
||||||
|
restart: always
|
||||||
|
depends_on:
|
||||||
|
- database
|
||||||
|
networks:
|
||||||
|
- traefik
|
||||||
|
- internal
|
||||||
|
labels:
|
||||||
|
- traefik.enable=true
|
||||||
|
- traefik.http.routers.hedgedoc.entrypoints=websecure
|
||||||
|
- traefik.http.routers.hedgedoc.rule=Host(`{{ hedgedoc_domain }}`)
|
||||||
|
- traefik.http.routers.hedgedoc.tls=true
|
||||||
|
- traefik.http.routers.hedgedoc.tls.certresolver=letsencrypt
|
||||||
|
- treafik.http.routers.hedgedoc.service=hedgedoc
|
||||||
|
- traefik.http.services.hedgedoc.loadbalancer.server.port=3000
|
||||||
|
- traefik.docker.network=traefik
|
14
ansible/roles/hedgedoc/vars/main.yml
Normal file
14
ansible/roles/hedgedoc/vars/main.yml
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
service_name: hedgedoc
|
||||||
|
data_dir: "{{ base_data_dir }}/{{ service_name }}"
|
||||||
|
service_dir: "{{ base_service_dir }}/{{ service_name }}"
|
||||||
|
hedgedoc_domain: "md.{{ domain_name_pim }}"
|
||||||
|
session_secret: !vault |
|
||||||
|
$ANSIBLE_VAULT;1.1;AES256
|
||||||
|
30633835386265643561343033326536653166343630396139303137613138383233666565666330
|
||||||
|
3032613865333836656566626435383165396539323837350a376331306464643766373839386638
|
||||||
|
65653865343539633636323833343964636332636461386434386432306230343833343431363134
|
||||||
|
6563373138626637650a633932313862326231666330343662343765666166373961376237396434
|
||||||
|
33396131353830323063326266623862353731653665626466653335656434303033353333353164
|
||||||
|
61613535373037646565386131383631366338616565373261396136616433393462313537313861
|
||||||
|
35313661616365373231373963323865393635626132343138363230313431636333363130346239
|
||||||
|
32656335333635613736
|
|
@ -1,3 +1,2 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
- role: common
|
|
||||||
- role: docker
|
- role: docker
|
2
ansible/roles/jitsi/meta/main.yml
Normal file
2
ansible/roles/jitsi/meta/main.yml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
dependencies:
|
||||||
|
- role: traefik
|
|
@ -1,3 +1,2 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
- role: common
|
|
||||||
- role: docker
|
- role: docker
|
2
ansible/roles/mastodon/meta/main.yml
Normal file
2
ansible/roles/mastodon/meta/main.yml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
dependencies:
|
||||||
|
- role: traefik
|
2
ansible/roles/overleaf/meta/main.yml
Normal file
2
ansible/roles/overleaf/meta/main.yml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
dependencies:
|
||||||
|
- role: traefik
|
13
ansible/roles/overleaf/tasks/main.yml
Normal file
13
ansible/roles/overleaf/tasks/main.yml
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
- name: Create service directory
|
||||||
|
file:
|
||||||
|
path: "{{ service_dir }}"
|
||||||
|
state: directory
|
||||||
|
- name: Copy Docker Compose script
|
||||||
|
template:
|
||||||
|
src: "{{ role_path }}/templates/docker-compose.yml.j2"
|
||||||
|
dest: "{{ service_dir }}/docker-compose.yml"
|
||||||
|
- name: Start the Docker Compose
|
||||||
|
docker_compose:
|
||||||
|
project_src: "{{ service_dir }}"
|
||||||
|
pull: true
|
||||||
|
remove_orphans: true
|
107
ansible/roles/overleaf/templates/docker-compose.yml.j2
Normal file
107
ansible/roles/overleaf/templates/docker-compose.yml.j2
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
version: '2.2'
|
||||||
|
|
||||||
|
networks:
|
||||||
|
traefik:
|
||||||
|
external: true
|
||||||
|
internal:
|
||||||
|
external: false
|
||||||
|
|
||||||
|
services:
|
||||||
|
sharelatex:
|
||||||
|
restart: always
|
||||||
|
image: sharelatex/sharelatex
|
||||||
|
container_name: overleaf
|
||||||
|
networks:
|
||||||
|
- traefik
|
||||||
|
- internal
|
||||||
|
depends_on:
|
||||||
|
overleaf-mongodb:
|
||||||
|
condition: service_healthy
|
||||||
|
overleaf-redis:
|
||||||
|
condition: service_started
|
||||||
|
links:
|
||||||
|
- overleaf-mongodb
|
||||||
|
- overleaf-redis
|
||||||
|
stop_grace_period: 60s
|
||||||
|
volumes:
|
||||||
|
- {{ data_dir }}/overleaf/sharelatex_data:/var/lib/sharelatex
|
||||||
|
labels:
|
||||||
|
- traefik.enable=true
|
||||||
|
- traefik.http.routers.overleaf.entrypoints=websecure
|
||||||
|
- traefik.http.routers.overleaf.rule=Host(`latex.pim.kunis.nl`)
|
||||||
|
- traefik.http.routers.overleaf.tls=true
|
||||||
|
- traefik.http.routers.overleaf.tls.certresolver=letsencrypt
|
||||||
|
- treafik.http.routers.overleaf.service=overleaf
|
||||||
|
- traefik.http.services.overleaf.loadbalancer.server.port=80
|
||||||
|
- traefik.docker.network=traefik
|
||||||
|
environment:
|
||||||
|
SHARELATEX_APP_NAME: Overleaf Community Edition
|
||||||
|
|
||||||
|
SHARELATEX_MONGO_URL: mongodb://overleaf-mongodb:27017/sharelatex
|
||||||
|
|
||||||
|
# Same property, unfortunately with different names in
|
||||||
|
# different locations
|
||||||
|
SHARELATEX_REDIS_HOST: overleaf-redis
|
||||||
|
REDIS_HOST: overleaf-redis
|
||||||
|
|
||||||
|
ENABLED_LINKED_FILE_TYPES: 'project_file,project_output_file'
|
||||||
|
|
||||||
|
# Enables Thumbnail generation using ImageMagick
|
||||||
|
ENABLE_CONVERSIONS: 'true'
|
||||||
|
|
||||||
|
# Disables email confirmation requirement
|
||||||
|
EMAIL_CONFIRMATION_DISABLED: 'true'
|
||||||
|
|
||||||
|
# temporary fix for LuaLaTex compiles
|
||||||
|
# see https://github.com/overleaf/overleaf/issues/695
|
||||||
|
TEXMFVAR: /var/lib/sharelatex/tmp/texmf-var
|
||||||
|
|
||||||
|
## Set for SSL via nginx-proxy
|
||||||
|
#VIRTUAL_HOST: 103.112.212.22
|
||||||
|
|
||||||
|
SHARELATEX_SITE_URL: https://latex.pim.kunis.nl
|
||||||
|
# SHARELATEX_NAV_TITLE: Our ShareLaTeX Instance
|
||||||
|
# SHARELATEX_HEADER_IMAGE_URL: http://somewhere.com/mylogo.png
|
||||||
|
SHARELATEX_ADMIN_EMAIL: pim@kunis.nl
|
||||||
|
|
||||||
|
# SHARELATEX_LEFT_FOOTER: '[{"text": "Powered by <a href=\"https://www.sharelatex.com\">ShareLaTeX</a> 2016"},{"text": "Another page I want to link to can be found <a href=\"here\">here</a>"} ]'
|
||||||
|
# SHARELATEX_RIGHT_FOOTER: '[{"text": "Hello I am on the Right"} ]'
|
||||||
|
|
||||||
|
SHARELATEX_EMAIL_FROM_ADDRESS: "noreply@kunis.nl"
|
||||||
|
|
||||||
|
SHARELATEX_EMAIL_SMTP_HOST: "smtp.tweak.nl"
|
||||||
|
SHARELATEX_EMAIL_SMTP_PORT: 587
|
||||||
|
SHARELATEX_EMAIL_SMTP_USER: ""
|
||||||
|
SHARELATEX_EMAIL_SMTP_PASS: ""
|
||||||
|
# SHARELATEX_EMAIL_SMTP_TLS_REJECT_UNAUTH: true
|
||||||
|
# SHARELATEX_EMAIL_SMTP_IGNORE_TLS: false
|
||||||
|
# SHARELATEX_EMAIL_SMTP_NAME: '127.0.0.1'
|
||||||
|
# SHARELATEX_EMAIL_SMTP_LOGGER: true
|
||||||
|
# SHARELATEX_CUSTOM_EMAIL_FOOTER: "This system is run by department x"
|
||||||
|
|
||||||
|
overleaf-mongodb:
|
||||||
|
restart: always
|
||||||
|
image: mongo:4.4
|
||||||
|
container_name: overleaf-mongodb
|
||||||
|
networks:
|
||||||
|
- internal
|
||||||
|
expose:
|
||||||
|
- 27017
|
||||||
|
volumes:
|
||||||
|
- {{ data_dir }}/overleaf/mongo_data:/data/db
|
||||||
|
healthcheck:
|
||||||
|
test: echo 'db.stats().ok' | mongo localhost:27017/test --quiet
|
||||||
|
interval: 10s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 5
|
||||||
|
|
||||||
|
overleaf-redis:
|
||||||
|
restart: always
|
||||||
|
image: redis:5
|
||||||
|
container_name: overleaf-redis
|
||||||
|
networks:
|
||||||
|
- internal
|
||||||
|
expose:
|
||||||
|
- 6379
|
||||||
|
volumes:
|
||||||
|
- {{ data_dir }}/overleaf/redis_data:/data
|
3
ansible/roles/overleaf/vars/main.yml
Normal file
3
ansible/roles/overleaf/vars/main.yml
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
service_name: overleaf
|
||||||
|
data_dir: "{{ base_data_dir}}/{{service_name}}"
|
||||||
|
service_dir: "{{ base_service_dir}}/{{service_name}}"
|
|
@ -1,3 +1,2 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
- role: common
|
|
||||||
- role: docker
|
- role: docker
|
|
@ -9,7 +9,7 @@ stock = utf-8
|
||||||
[auth]
|
[auth]
|
||||||
realm = Radicale - Password Required
|
realm = Radicale - Password Required
|
||||||
type = htpasswd
|
type = htpasswd
|
||||||
htpasswd_filename = /radicale/users
|
htpasswd_filename = /config/users
|
||||||
htpasswd_encryption = md5
|
htpasswd_encryption = md5
|
||||||
|
|
||||||
[rights]
|
[rights]
|
2
ansible/roles/radicale/meta/main.yml
Normal file
2
ansible/roles/radicale/meta/main.yml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
dependencies:
|
||||||
|
- role: traefik
|
|
@ -13,7 +13,7 @@
|
||||||
- name: Copy radicale.conf
|
- name: Copy radicale.conf
|
||||||
copy:
|
copy:
|
||||||
src: "{{ role_path }}/files/radicale.conf"
|
src: "{{ role_path }}/files/radicale.conf"
|
||||||
dest: "{{ service_dir }}/config/radicale.conf"
|
dest: "{{ service_dir }}/config/config"
|
||||||
- name: Copy users file
|
- name: Copy users file
|
||||||
copy:
|
copy:
|
||||||
src: "{{ role_path }}/files/users"
|
src: "{{ role_path }}/files/users"
|
|
@ -1,18 +1,28 @@
|
||||||
version: '3'
|
version: '3.7'
|
||||||
|
|
||||||
networks:
|
|
||||||
traefik:
|
|
||||||
external: true
|
|
||||||
|
|
||||||
services:
|
services:
|
||||||
radicale:
|
radicale:
|
||||||
restart: always
|
image: tomsquest/docker-radicale
|
||||||
image: mailu/radicale:1.9
|
|
||||||
container_name: radicale
|
container_name: radicale
|
||||||
|
init: true
|
||||||
|
read_only: true
|
||||||
|
security_opt:
|
||||||
|
- no-new-privileges:true
|
||||||
|
cap_drop:
|
||||||
|
- ALL
|
||||||
|
cap_add:
|
||||||
|
- SETUID
|
||||||
|
- SETGID
|
||||||
|
- CHOWN
|
||||||
|
- KILL
|
||||||
|
healthcheck:
|
||||||
|
test: curl -f http://127.0.0.1:5232 || exit 1
|
||||||
|
interval: 30s
|
||||||
|
retries: 3
|
||||||
|
restart: unless-stopped
|
||||||
volumes:
|
volumes:
|
||||||
- {{ data_dir }}:/data
|
- {{ data_dir }}:/data
|
||||||
- {{ service_dir }}/config:/radicale
|
- {{ service_dir }}/config:/config:ro
|
||||||
command: radicale -S -C /radicale/radicale.conf
|
|
||||||
networks:
|
networks:
|
||||||
- traefik
|
- traefik
|
||||||
labels:
|
labels:
|
||||||
|
@ -23,3 +33,7 @@ services:
|
||||||
- traefik.http.routers.radicale.tls.certresolver=letsencrypt
|
- traefik.http.routers.radicale.tls.certresolver=letsencrypt
|
||||||
- traefik.http.routers.radicale.service=radicale
|
- traefik.http.routers.radicale.service=radicale
|
||||||
- traefik.http.services.radicale.loadbalancer.server.port=5232
|
- traefik.http.services.radicale.loadbalancer.server.port=5232
|
||||||
|
|
||||||
|
networks:
|
||||||
|
traefik:
|
||||||
|
external: true
|
2
ansible/roles/seafile/meta/main.yml
Normal file
2
ansible/roles/seafile/meta/main.yml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
dependencies:
|
||||||
|
- role: traefik
|
2
ansible/roles/static/meta/main.yml
Normal file
2
ansible/roles/static/meta/main.yml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
dependencies:
|
||||||
|
- role: traefik
|
|
@ -1,4 +1,2 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
- role: common
|
|
||||||
- role: docker
|
- role: docker
|
||||||
|
|
2
ansible/roles/traefik/meta/main.yml
Normal file
2
ansible/roles/traefik/meta/main.yml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
dependencies:
|
||||||
|
- role: docker
|
|
@ -2,10 +2,14 @@
|
||||||
file:
|
file:
|
||||||
path: "{{ service_dir }}"
|
path: "{{ service_dir }}"
|
||||||
state: directory
|
state: directory
|
||||||
|
- name: Create data directory
|
||||||
|
file:
|
||||||
|
path: "{{ data_dir }}"
|
||||||
|
state: directory
|
||||||
- name: Create acme file
|
- name: Create acme file
|
||||||
copy:
|
copy:
|
||||||
content: ""
|
content: ""
|
||||||
dest: "{{ service_dir }}/acme.json"
|
dest: "{{ data_dir }}/acme.json"
|
||||||
force: no
|
force: no
|
||||||
mode: 0600
|
mode: 0600
|
||||||
- name: Copy Docker Compose script
|
- name: Copy Docker Compose script
|
|
@ -18,7 +18,7 @@ services:
|
||||||
- /var/run/docker.sock:/var/run/docker.sock
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
- {{ service_dir }}/traefik.toml:/etc/traefik/traefik.toml
|
- {{ service_dir }}/traefik.toml:/etc/traefik/traefik.toml
|
||||||
- {{ service_dir }}/services.toml:/etc/traefik/services.toml
|
- {{ service_dir }}/services.toml:/etc/traefik/services.toml
|
||||||
- {{ service_dir }}/acme.json:/acme.json
|
- {{ data_dir }}/acme.json:/acme.json
|
||||||
networks:
|
networks:
|
||||||
- traefik
|
- traefik
|
||||||
labels:
|
labels:
|
|
@ -1,2 +1,3 @@
|
||||||
service_name: traefik
|
service_name: traefik
|
||||||
service_dir: "{{ base_service_dir }}/{{ service_name }}"
|
service_dir: "{{ base_service_dir }}/{{ service_name }}"
|
||||||
|
data_dir: "{{ base_data_dir }}/{{ service_name }}"
|
2
ansible/roles/watchtower/meta/main.yml
Normal file
2
ansible/roles/watchtower/meta/main.yml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
dependencies:
|
||||||
|
- role: docker
|
30
data/main.tf
30
data/main.tf
|
@ -1,30 +0,0 @@
|
||||||
terraform {
|
|
||||||
backend "pg" {
|
|
||||||
schema_name = "max-data"
|
|
||||||
conn_str = "postgres://terraform@10.42.0.1/terraform_state"
|
|
||||||
}
|
|
||||||
|
|
||||||
required_providers {
|
|
||||||
libvirt = {
|
|
||||||
source = "dmacvicar/libvirt"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
provider "libvirt" {
|
|
||||||
uri = "qemu+ssh://root@atlas.lan/system"
|
|
||||||
}
|
|
||||||
|
|
||||||
resource "libvirt_volume" "data" {
|
|
||||||
name = "max-data"
|
|
||||||
pool = "data"
|
|
||||||
size = 1024 * 1024 * 1024 * 65
|
|
||||||
|
|
||||||
lifecycle {
|
|
||||||
prevent_destroy = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
output "data_disk_id" {
|
|
||||||
value = libvirt_volume.data.id
|
|
||||||
}
|
|
27
main.tf
27
main.tf
|
@ -1,27 +0,0 @@
|
||||||
terraform {
|
|
||||||
backend "pg" {
|
|
||||||
schema_name = "max"
|
|
||||||
conn_str = "postgres://terraform@10.42.0.1/terraform_state"
|
|
||||||
}
|
|
||||||
|
|
||||||
required_providers {
|
|
||||||
libvirt = {
|
|
||||||
source = "dmacvicar/libvirt"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
provider "libvirt" {
|
|
||||||
uri = "qemu+ssh://root@atlas.lan/system"
|
|
||||||
}
|
|
||||||
|
|
||||||
module "tf-datatest" {
|
|
||||||
source = "git::https://git.pim.kunis.nl/home/tf-modules.git//debian"
|
|
||||||
name = "max2"
|
|
||||||
domain_name = "tf-max"
|
|
||||||
data_disk = "/kvm/data/max-data"
|
|
||||||
fixed_address = "192.168.30.66/24"
|
|
||||||
ansible_command = "ansible-playbook max.yml"
|
|
||||||
insecure_password = true
|
|
||||||
memory = 1024 * 8
|
|
||||||
}
|
|
36
max.yml
36
max.yml
|
@ -1,36 +0,0 @@
|
||||||
- name: Setup homeserver
|
|
||||||
hosts: max
|
|
||||||
gather_facts: no
|
|
||||||
|
|
||||||
pre_tasks:
|
|
||||||
- name: Wait for host to come up
|
|
||||||
wait_for:
|
|
||||||
state: started
|
|
||||||
port: 22
|
|
||||||
host: max2.dmz
|
|
||||||
timeout: 300
|
|
||||||
connect_timeout: 300
|
|
||||||
search_regex: OpenSSH
|
|
||||||
delegate_to: localhost
|
|
||||||
- name: Wait for cloud-init to finish
|
|
||||||
shell:
|
|
||||||
cmd: "cloud-init status --wait"
|
|
||||||
register: cloudinit
|
|
||||||
changed_when: "'..' in cloudinit.stdout"
|
|
||||||
- name: Gather facts
|
|
||||||
setup:
|
|
||||||
|
|
||||||
roles:
|
|
||||||
- {role: 'watchtower', tags: 'watchtower'}
|
|
||||||
- {role: 'forgejo', tags: 'forgejo'}
|
|
||||||
# - {role: 'syncthing', tags: 'syncthing'}
|
|
||||||
- {role: 'kms', tags: 'kms'}
|
|
||||||
- {role: 'cyberchef', tags: 'cyberchef'}
|
|
||||||
#- {role: 'radicale', tags: 'radicale'}
|
|
||||||
- {role: 'mastodon', tags: 'mastodon'}
|
|
||||||
- {role: 'seafile', tags: 'seafile'}
|
|
||||||
- {role: 'jitsi', tags: 'jitsi'}
|
|
||||||
- {role: 'freshrss', tags: 'freshrss'}
|
|
||||||
- {role: 'static', tags: 'static'}
|
|
||||||
- {role: 'inbucket', tags: 'inbucket'}
|
|
||||||
- {role: 'prometheus', tags: 'prometheus'}
|
|
|
@ -1,17 +0,0 @@
|
||||||
- name: APT upgrade
|
|
||||||
apt:
|
|
||||||
autoremove: true
|
|
||||||
upgrade: yes
|
|
||||||
state: latest
|
|
||||||
update_cache: yes
|
|
||||||
cache_valid_time: 86400 # One day
|
|
||||||
- name: Create base service directory
|
|
||||||
file:
|
|
||||||
path: "{{ base_service_dir }}"
|
|
||||||
state: directory
|
|
||||||
- name: Delete externally managed environment file
|
|
||||||
shell:
|
|
||||||
cmd: "rm /usr/lib/python*/EXTERNALLY-MANAGED"
|
|
||||||
register: rm
|
|
||||||
changed_when: "rm.rc == 0"
|
|
||||||
failed_when: "false"
|
|
|
@ -1,4 +0,0 @@
|
||||||
dependencies:
|
|
||||||
- role: common
|
|
||||||
- role: docker
|
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
{
|
|
||||||
"default-address-pools":
|
|
||||||
[
|
|
||||||
{"base":"10.204.0.0/16","size":24}
|
|
||||||
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,41 +0,0 @@
|
||||||
- name: Install Docker prerequisites
|
|
||||||
apt:
|
|
||||||
pkg:
|
|
||||||
- ca-certificates
|
|
||||||
- curl
|
|
||||||
- gnupg
|
|
||||||
- lsb-release
|
|
||||||
- python3-pip
|
|
||||||
- name: Add Docker APT key
|
|
||||||
apt_key:
|
|
||||||
url: https://download.docker.com/linux/ubuntu/gpg
|
|
||||||
keyring: /etc/apt/keyrings/docker.gpg
|
|
||||||
- name: Add Docker repository
|
|
||||||
apt_repository:
|
|
||||||
repo: "deb [signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian {{ ansible_distribution_release }} stable"
|
|
||||||
register: apt_repository
|
|
||||||
- name: Update APT cache
|
|
||||||
apt:
|
|
||||||
update_cache: true
|
|
||||||
when: apt_repository.changed
|
|
||||||
- name: Install Docker packages
|
|
||||||
apt:
|
|
||||||
pkg:
|
|
||||||
- docker-ce
|
|
||||||
- docker-ce-cli
|
|
||||||
- containerd.io
|
|
||||||
- docker-compose-plugin
|
|
||||||
- name: Install Docker modules for Python
|
|
||||||
pip:
|
|
||||||
name:
|
|
||||||
- docker
|
|
||||||
- docker-compose
|
|
||||||
- name: Copy daemon.json
|
|
||||||
copy:
|
|
||||||
src: "{{ role_path }}/files/daemon.json"
|
|
||||||
dest: /etc/docker/daemon.json
|
|
||||||
- name: Start Docker
|
|
||||||
systemd:
|
|
||||||
name: docker
|
|
||||||
enabled: true
|
|
||||||
state: started
|
|
|
@ -1,16 +0,0 @@
|
||||||
- name: Install firewalld
|
|
||||||
apt:
|
|
||||||
pkg:
|
|
||||||
- firewalld
|
|
||||||
state: latest
|
|
||||||
update_cache: true
|
|
||||||
- name: Allow SSH
|
|
||||||
firewalld:
|
|
||||||
service: ssh
|
|
||||||
permanent: yes
|
|
||||||
state: enabled
|
|
||||||
- name: Start firewalld
|
|
||||||
systemd:
|
|
||||||
enabled: true
|
|
||||||
name: sshd
|
|
||||||
state: started
|
|
|
@ -1,4 +0,0 @@
|
||||||
dependencies:
|
|
||||||
- role: common
|
|
||||||
- role: docker
|
|
||||||
- role: traefik
|
|
|
@ -1,4 +0,0 @@
|
||||||
dependencies:
|
|
||||||
- role: common
|
|
||||||
- role: docker
|
|
||||||
- role: traefik
|
|
|
@ -1,4 +0,0 @@
|
||||||
dependencies:
|
|
||||||
- role: common
|
|
||||||
- role: docker
|
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
dependencies:
|
|
||||||
- role: common
|
|
||||||
- role: docker
|
|
||||||
- role: traefik
|
|
|
@ -1,4 +0,0 @@
|
||||||
dependencies:
|
|
||||||
- role: common
|
|
||||||
- role: docker
|
|
||||||
- role: traefik
|
|
|
@ -1,4 +0,0 @@
|
||||||
dependencies:
|
|
||||||
- role: common
|
|
||||||
- role: docker
|
|
||||||
- role: traefik
|
|
|
@ -1,4 +0,0 @@
|
||||||
dependencies:
|
|
||||||
- role: common
|
|
||||||
- role: docker
|
|
||||||
- role: traefik
|
|
|
@ -1,54 +0,0 @@
|
||||||
# This is the ssh client system-wide configuration file. See
|
|
||||||
# ssh_config(5) for more information. This file provides defaults for
|
|
||||||
# users, and the values can be changed in per-user configuration files
|
|
||||||
# or on the command line.
|
|
||||||
|
|
||||||
# Configuration data is parsed as follows:
|
|
||||||
# 1. command line options
|
|
||||||
# 2. user-specific file
|
|
||||||
# 3. system-wide file
|
|
||||||
# Any configuration value is only changed the first time it is set.
|
|
||||||
# Thus, host-specific definitions should be at the beginning of the
|
|
||||||
# configuration file, and defaults at the end.
|
|
||||||
|
|
||||||
# Site-wide defaults for some commonly used options. For a comprehensive
|
|
||||||
# list of available options, their meanings and defaults, please see the
|
|
||||||
# ssh_config(5) man page.
|
|
||||||
|
|
||||||
Include /etc/ssh/ssh_config.d/*.conf
|
|
||||||
|
|
||||||
Host *
|
|
||||||
# ForwardAgent no
|
|
||||||
# ForwardX11 no
|
|
||||||
# ForwardX11Trusted yes
|
|
||||||
# PasswordAuthentication yes
|
|
||||||
# HostbasedAuthentication no
|
|
||||||
# GSSAPIAuthentication no
|
|
||||||
# GSSAPIDelegateCredentials no
|
|
||||||
# GSSAPIKeyExchange no
|
|
||||||
# GSSAPITrustDNS no
|
|
||||||
# BatchMode no
|
|
||||||
# CheckHostIP yes
|
|
||||||
# AddressFamily any
|
|
||||||
# ConnectTimeout 0
|
|
||||||
# StrictHostKeyChecking ask
|
|
||||||
# IdentityFile ~/.ssh/id_rsa
|
|
||||||
# IdentityFile ~/.ssh/id_dsa
|
|
||||||
# IdentityFile ~/.ssh/id_ecdsa
|
|
||||||
# IdentityFile ~/.ssh/id_ed25519
|
|
||||||
# Port 22
|
|
||||||
# Ciphers aes128-ctr,aes192-ctr,aes256-ctr,aes128-cbc,3des-cbc
|
|
||||||
# MACs hmac-md5,hmac-sha1,umac-64@openssh.com
|
|
||||||
# EscapeChar ~
|
|
||||||
# Tunnel no
|
|
||||||
# TunnelDevice any:any
|
|
||||||
# PermitLocalCommand no
|
|
||||||
# VisualHostKey no
|
|
||||||
# ProxyCommand ssh -q -W %h:%p gateway.example.com
|
|
||||||
# RekeyLimit 1G 1h
|
|
||||||
# UserKnownHostsFile ~/.ssh/known_hosts.d/%k
|
|
||||||
SendEnv LANG LC_*
|
|
||||||
|
|
||||||
# set HashKnownHosts to no to make known_hosts human readable and reviewable.
|
|
||||||
# HashKnownHosts yes
|
|
||||||
# GSSAPIAuthentication yes
|
|
|
@ -1,41 +0,0 @@
|
||||||
Include /etc/ssh/sshd_config.d/*.conf
|
|
||||||
|
|
||||||
HostKey /etc/ssh/ssh_host_ed25519_key
|
|
||||||
|
|
||||||
# Ciphers and keying
|
|
||||||
HostKeyAlgorithms ssh-ed25519
|
|
||||||
CASignatureAlgorithms ssh-ed25519
|
|
||||||
HostbasedAcceptedKeyTypes ssh-ed25519
|
|
||||||
HostKeyAlgorithms ssh-ed25519
|
|
||||||
KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org
|
|
||||||
Ciphers chacha20-poly1305@openssh.com
|
|
||||||
MACs hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com
|
|
||||||
|
|
||||||
# To disable tunneled clear text passwords, change to no here!
|
|
||||||
PasswordAuthentication no
|
|
||||||
PermitEmptyPasswords no
|
|
||||||
|
|
||||||
# Change to yes to enable challenge-response passwords (beware issues with
|
|
||||||
# some PAM modules and threads)
|
|
||||||
KbdInteractiveAuthentication no
|
|
||||||
|
|
||||||
# Set this to 'yes' to enable PAM authentication, account processing,
|
|
||||||
# and session processing. If this is enabled, PAM authentication will
|
|
||||||
# be allowed through the KbdInteractiveAuthentication and
|
|
||||||
# PasswordAuthentication. Depending on your PAM configuration,
|
|
||||||
# PAM authentication via KbdInteractiveAuthentication may bypass
|
|
||||||
# the setting of "PermitRootLogin without-password".
|
|
||||||
# If you just want the PAM account and session checks to run without
|
|
||||||
# PAM authentication, then enable this but set PasswordAuthentication
|
|
||||||
# and KbdInteractiveAuthentication to 'no'.
|
|
||||||
UsePAM yes
|
|
||||||
|
|
||||||
X11Forwarding yes
|
|
||||||
PrintMotd no
|
|
||||||
|
|
||||||
# Allow client to pass locale environment variables
|
|
||||||
AcceptEnv LANG LC_*
|
|
||||||
|
|
||||||
# override default of no subsystems
|
|
||||||
Subsystem sftp /usr/lib/openssh/sftp-server
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Reference in a new issue