feat: Create docker outpost
This commit is contained in:
parent
293e18a821
commit
993a91f380
@ -1,3 +1,5 @@
|
|||||||
dns_server:
|
dns_server:
|
||||||
admin_username: "{{ secrets.admin_username }}"
|
admin_username: "{{ secrets.admin_username }}"
|
||||||
admin_password: "{{ secrets.admin_password }}"
|
admin_password: "{{ secrets.admin_password }}"
|
||||||
|
|
||||||
|
portainer_agent_secret: "{{ secrets.portainer_agent_secret }}"
|
||||||
|
73
ansible/jumper.yml
Normal file
73
ansible/jumper.yml
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
---
|
||||||
|
- name: Install
|
||||||
|
hosts: jumper
|
||||||
|
remote_user: ubuntu
|
||||||
|
vars:
|
||||||
|
pv_disks:
|
||||||
|
- /dev/sda
|
||||||
|
vg_name: vg1
|
||||||
|
lv_name: pvs
|
||||||
|
lv_size: +100%FREE
|
||||||
|
fs_type: ext4
|
||||||
|
mount_path: /mnt/docker
|
||||||
|
extra_docker_daemon_options: |
|
||||||
|
"data-root": "/mnt/docker/docker-root"
|
||||||
|
tasks:
|
||||||
|
- import_role: name=dns-client
|
||||||
|
|
||||||
|
- import_role: name=lvm
|
||||||
|
|
||||||
|
- name: Ensure docker root exists
|
||||||
|
become: true
|
||||||
|
file:
|
||||||
|
path: /mnt/docker/docker-root
|
||||||
|
state: directory
|
||||||
|
mode: "0755"
|
||||||
|
|
||||||
|
- import_role: name=docker
|
||||||
|
|
||||||
|
- name: Run portainer agent
|
||||||
|
become: true
|
||||||
|
docker_container:
|
||||||
|
name: portainer_agent
|
||||||
|
image: portainer/agent:2.16.2
|
||||||
|
ports:
|
||||||
|
- "9001:9001"
|
||||||
|
env:
|
||||||
|
AGENT_SECRET: "{{ portainer_agent_secret }}"
|
||||||
|
restart_policy: unless-stopped
|
||||||
|
mounts:
|
||||||
|
- type: bind
|
||||||
|
source: /var/run/docker.sock
|
||||||
|
target: /var/run/docker.sock
|
||||||
|
- type: bind
|
||||||
|
source: /mnt/docker/docker-root/volumes
|
||||||
|
target: /var/lib/docker/volumes
|
||||||
|
|
||||||
|
- name: Mount extra shares
|
||||||
|
tags: [extra-shares]
|
||||||
|
hosts: jumper
|
||||||
|
vars:
|
||||||
|
shares:
|
||||||
|
- src: truenas.local:/mnt/emc14t9/lfs/media
|
||||||
|
path: /mnt/media
|
||||||
|
opts: rw,_netdev,hard,intr,nolock
|
||||||
|
fstype: nfs
|
||||||
|
state: mounted
|
||||||
|
tasks:
|
||||||
|
- name: Ensure mount directory exists
|
||||||
|
become: true
|
||||||
|
file:
|
||||||
|
path: "{{ item.path }}"
|
||||||
|
state: directory
|
||||||
|
mode: '0755'
|
||||||
|
loop: "{{ shares }}"
|
||||||
|
- name: Mount media share
|
||||||
|
become: true
|
||||||
|
mount:
|
||||||
|
src: "{{ item.src }}"
|
||||||
|
path: "{{ item.path }}"
|
||||||
|
opts: "{{ item.opts }}"
|
||||||
|
state: "{{ item.state | default('mounted') }}"
|
||||||
|
fstype: "{{ item.fstype }}"
|
||||||
|
loop: "{{ shares }}"
|
@ -10,33 +10,5 @@
|
|||||||
lv_size: "{{ lvm.lv_size }}"
|
lv_size: "{{ lvm.lv_size }}"
|
||||||
fs_type: "{{ lvm.fs_type }}"
|
fs_type: "{{ lvm.fs_type }}"
|
||||||
mount_path: "{{ lvm.mount_path }}"
|
mount_path: "{{ lvm.mount_path }}"
|
||||||
tasks:
|
roles:
|
||||||
- name: Create a volume group
|
- lvm
|
||||||
community.general.lvg:
|
|
||||||
vg: "{{ vg_name }}"
|
|
||||||
pvs: "{{ pv_disks }}"
|
|
||||||
pvresize: yes
|
|
||||||
|
|
||||||
- name: Create Logical Volume for data persistence
|
|
||||||
community.general.lvol:
|
|
||||||
vg: "{{ vg_name }}"
|
|
||||||
lv: "{{ lv_name }}"
|
|
||||||
size: "{{ lv_size }}"
|
|
||||||
|
|
||||||
- name: Create filesystem on LV
|
|
||||||
community.general.filesystem:
|
|
||||||
fstype: "{{ fs_type }}"
|
|
||||||
resizefs: true
|
|
||||||
dev: /dev/mapper/{{ vg_name }}-{{ lv_name }}
|
|
||||||
|
|
||||||
- name: Get LV UUID
|
|
||||||
ansible.builtin.command: lsblk /dev/mapper/{{ vg_name }}-{{ lv_name }} -no UUID
|
|
||||||
register: lv_uuid
|
|
||||||
changed_when: false
|
|
||||||
|
|
||||||
- name: Mount created filesystem
|
|
||||||
ansible.posix.mount:
|
|
||||||
path: "{{ mount_path }}"
|
|
||||||
src: UUID={{ lv_uuid.stdout }}
|
|
||||||
state: mounted
|
|
||||||
fstype: "{{ fs_type }}"
|
|
||||||
|
20
ansible/roles/dns-client/tasks/main.yml
Normal file
20
ansible/roles/dns-client/tasks/main.yml
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
- name: Set DNS servers
|
||||||
|
become: true
|
||||||
|
tags: [set_dns_servers]
|
||||||
|
copy:
|
||||||
|
content: |
|
||||||
|
[Resolve]
|
||||||
|
DNS=10.0.123.123
|
||||||
|
# FallbackDNS=1.1.1.1
|
||||||
|
dest: /etc/systemd/resolved.conf
|
||||||
|
register: dns_servers_configuration
|
||||||
|
|
||||||
|
- name: Restart systemd-resolved
|
||||||
|
tags: [set_dns_servers]
|
||||||
|
service:
|
||||||
|
name: systemd-resolved
|
||||||
|
state: restarted
|
||||||
|
when: dns_servers_configuration.changed
|
||||||
|
retries: 2
|
||||||
|
|
@ -1,52 +1,4 @@
|
|||||||
---
|
---
|
||||||
- name: Create /etc/docker
|
|
||||||
become: true
|
|
||||||
file:
|
|
||||||
path: /etc/docker
|
|
||||||
state: directory
|
|
||||||
mode: '0755'
|
|
||||||
|
|
||||||
- name: Set docker daemon settings
|
|
||||||
become: true
|
|
||||||
# Otherwise we risk conflicts on the host subnet
|
|
||||||
copy:
|
|
||||||
content: |
|
|
||||||
{
|
|
||||||
"default-address-pools": [
|
|
||||||
{
|
|
||||||
"base": "172.17.0.0/12",
|
|
||||||
"size": 20
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"base": "172.168.0.0/16",
|
|
||||||
"size": 24
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"dns": ["10.0.123.123"]
|
|
||||||
}
|
|
||||||
dest: /etc/docker/daemon.json
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
become: true
|
|
||||||
apt:
|
|
||||||
name:
|
|
||||||
- python3
|
|
||||||
- python3-pip
|
|
||||||
- python3-docker
|
|
||||||
- docker.io
|
|
||||||
- docker-buildx
|
|
||||||
- docker-compose-v2
|
|
||||||
- python3-jsondiff
|
|
||||||
- apache2-utils
|
|
||||||
update_cache: yes
|
|
||||||
|
|
||||||
- name: Enable docker
|
|
||||||
become: true
|
|
||||||
service:
|
|
||||||
name: docker
|
|
||||||
state: started
|
|
||||||
enabled: true
|
|
||||||
|
|
||||||
- name: Init swarm
|
- name: Init swarm
|
||||||
when: inventory_hostname == groups.swarm_managers[0]
|
when: inventory_hostname == groups.swarm_managers[0]
|
||||||
become: true
|
become: true
|
||||||
|
1
ansible/roles/docker/defaults/main.yml
Normal file
1
ansible/roles/docker/defaults/main.yml
Normal file
@ -0,0 +1 @@
|
|||||||
|
extra_docker_daemon_options: ""
|
51
ansible/roles/docker/tasks/main.yml
Normal file
51
ansible/roles/docker/tasks/main.yml
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
---
|
||||||
|
- name: Create /etc/docker
|
||||||
|
become: true
|
||||||
|
file:
|
||||||
|
path: /etc/docker
|
||||||
|
state: directory
|
||||||
|
mode: '0755'
|
||||||
|
|
||||||
|
- name: Set docker daemon settings
|
||||||
|
become: true
|
||||||
|
# Otherwise we risk conflicts on the host subnet
|
||||||
|
copy:
|
||||||
|
content: |
|
||||||
|
{
|
||||||
|
{{ extra_docker_daemon_options }},
|
||||||
|
"default-address-pools": [
|
||||||
|
{
|
||||||
|
"base": "172.17.0.0/12",
|
||||||
|
"size": 20
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"base": "172.168.0.0/16",
|
||||||
|
"size": 24
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"dns": ["10.0.123.123"]
|
||||||
|
}
|
||||||
|
dest: /etc/docker/daemon.json
|
||||||
|
register: docker_daemon_conf
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
become: true
|
||||||
|
apt:
|
||||||
|
name:
|
||||||
|
- python3
|
||||||
|
- python3-pip
|
||||||
|
- python3-docker
|
||||||
|
- docker.io
|
||||||
|
- docker-buildx
|
||||||
|
- docker-compose-v2
|
||||||
|
- python3-jsondiff
|
||||||
|
- apache2-utils
|
||||||
|
update_cache: yes
|
||||||
|
|
||||||
|
- name: Enable docker
|
||||||
|
become: true
|
||||||
|
service:
|
||||||
|
name: docker
|
||||||
|
state: "{{ 'restarted' if docker_daemon_conf.changed else 'started' }}"
|
||||||
|
enabled: true
|
||||||
|
|
36
ansible/roles/lvm/tasks/main.yml
Normal file
36
ansible/roles/lvm/tasks/main.yml
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
---
|
||||||
|
- name: Create a volume group
|
||||||
|
become: true
|
||||||
|
community.general.lvg:
|
||||||
|
vg: "{{ vg_name }}"
|
||||||
|
pvs: "{{ pv_disks }}"
|
||||||
|
pvresize: yes
|
||||||
|
|
||||||
|
- name: Create Logical Volume for data persistence
|
||||||
|
become: true
|
||||||
|
community.general.lvol:
|
||||||
|
vg: "{{ vg_name }}"
|
||||||
|
lv: "{{ lv_name }}"
|
||||||
|
size: "{{ lv_size }}"
|
||||||
|
|
||||||
|
- name: Create filesystem on LV
|
||||||
|
become: true
|
||||||
|
community.general.filesystem:
|
||||||
|
fstype: "{{ fs_type }}"
|
||||||
|
resizefs: true
|
||||||
|
dev: /dev/mapper/{{ vg_name }}-{{ lv_name }}
|
||||||
|
|
||||||
|
- name: Get LV UUID
|
||||||
|
become: true
|
||||||
|
ansible.builtin.command: lsblk /dev/mapper/{{ vg_name }}-{{ lv_name }} -no UUID
|
||||||
|
register: lv_uuid
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Mount created filesystem
|
||||||
|
become: true
|
||||||
|
ansible.posix.mount:
|
||||||
|
path: "{{ mount_path }}"
|
||||||
|
src: UUID={{ lv_uuid.stdout }}
|
||||||
|
state: mounted
|
||||||
|
fstype: "{{ fs_type }}"
|
||||||
|
|
@ -8,24 +8,6 @@
|
|||||||
state: mounted
|
state: mounted
|
||||||
fstype: nfs
|
fstype: nfs
|
||||||
|
|
||||||
- name: Set DNS servers
|
|
||||||
become: true
|
|
||||||
tags: [set_dns_servers]
|
|
||||||
copy:
|
|
||||||
content: |
|
|
||||||
[Resolve]
|
|
||||||
DNS=10.0.123.123
|
|
||||||
# FallbackDNS=1.1.1.1
|
|
||||||
dest: /etc/systemd/resolved.conf
|
|
||||||
register: dns_servers_configuration
|
|
||||||
|
|
||||||
- name: Restart systemd-resolved
|
|
||||||
tags: [set_dns_servers]
|
|
||||||
service:
|
|
||||||
name: systemd-resolved
|
|
||||||
state: restarted
|
|
||||||
when: dns_servers_configuration.changed
|
|
||||||
retries: 2
|
|
||||||
|
|
||||||
- import_tasks: traefik.yml
|
- import_tasks: traefik.yml
|
||||||
- import_tasks: portainer.yml
|
- import_tasks: portainer.yml
|
||||||
|
@ -3,15 +3,6 @@ networks:
|
|||||||
traefik:
|
traefik:
|
||||||
external: true
|
external: true
|
||||||
|
|
||||||
volumes:
|
|
||||||
portainer_data:
|
|
||||||
driver: local
|
|
||||||
driver_opts:
|
|
||||||
o: bind
|
|
||||||
type: none
|
|
||||||
device: {{nfs_mount_path}}/portainer/data
|
|
||||||
name: portainer_data
|
|
||||||
|
|
||||||
services:
|
services:
|
||||||
agent:
|
agent:
|
||||||
image: portainer/agent:latest
|
image: portainer/agent:latest
|
||||||
@ -34,7 +25,7 @@ services:
|
|||||||
- "9000:9000"
|
- "9000:9000"
|
||||||
- "8000:8000"
|
- "8000:8000"
|
||||||
volumes:
|
volumes:
|
||||||
- portainer_data:/data
|
- {{nfs_mount_path}}/portainer/data:/data
|
||||||
networks:
|
networks:
|
||||||
- portainer
|
- portainer
|
||||||
- traefik
|
- traefik
|
||||||
|
@ -2,6 +2,9 @@ api:
|
|||||||
dashboard: true
|
dashboard: true
|
||||||
insecure: true
|
insecure: true
|
||||||
|
|
||||||
|
# accessLog:
|
||||||
|
# filePath: /var/log/traefik/access.log
|
||||||
|
|
||||||
providers:
|
providers:
|
||||||
swarm:
|
swarm:
|
||||||
exposedByDefault: false
|
exposedByDefault: false
|
||||||
|
@ -4,15 +4,6 @@ networks:
|
|||||||
attachable: true
|
attachable: true
|
||||||
name: traefik
|
name: traefik
|
||||||
|
|
||||||
volumes:
|
|
||||||
traefik:
|
|
||||||
driver: local
|
|
||||||
driver_opts:
|
|
||||||
o: bind
|
|
||||||
type: none
|
|
||||||
device: {{nfs_mount_path}}/traefik
|
|
||||||
name: traefik
|
|
||||||
|
|
||||||
secrets:
|
secrets:
|
||||||
cf_dns_api_token:
|
cf_dns_api_token:
|
||||||
file: "{{nfs_mount_path}}/traefik/secrets/cf-dns-api-token.secret"
|
file: "{{nfs_mount_path}}/traefik/secrets/cf-dns-api-token.secret"
|
||||||
@ -34,7 +25,7 @@ services:
|
|||||||
- "CF_DNS_API_TOKEN_FILE=/run/secrets/cf_dns_api_token"
|
- "CF_DNS_API_TOKEN_FILE=/run/secrets/cf_dns_api_token"
|
||||||
volumes:
|
volumes:
|
||||||
- /var/run/docker.sock:/var/run/docker.sock
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
- traefik:/data
|
- {{nfs_mount_path}}/traefik:/data
|
||||||
networks:
|
networks:
|
||||||
- traefik
|
- traefik
|
||||||
deploy:
|
deploy:
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
hosts: swarm
|
hosts: swarm
|
||||||
tags: [swarm-init]
|
tags: [swarm-init]
|
||||||
roles:
|
roles:
|
||||||
|
- dns-client
|
||||||
|
- docker
|
||||||
- docker-swarm
|
- docker-swarm
|
||||||
- swarm-bootstrap
|
- swarm-bootstrap
|
||||||
|
|
||||||
|
@ -1,16 +1,15 @@
|
|||||||
---
|
---
|
||||||
version: "3.8"
|
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
traefik:
|
traefik:
|
||||||
external: true
|
external: true
|
||||||
media:
|
media:
|
||||||
|
|
||||||
# Argh, mounting the configuration on the NFS drive is not a good idea!
|
volumes:
|
||||||
# The sqlite databases in these volumes can have pretty high random RW, so
|
jellyseerr_config:
|
||||||
# we should keep these local. But fuck, managing them on a non-network drive
|
transmission_config:
|
||||||
# on Swarm is such a pain...
|
prowlarr_config:
|
||||||
# Maybe we can get these to connect to a different DB?
|
radarr_config:
|
||||||
|
sonarr_config:
|
||||||
|
|
||||||
services:
|
services:
|
||||||
transmission-openvpn:
|
transmission-openvpn:
|
||||||
@ -21,7 +20,7 @@ services:
|
|||||||
- traefik
|
- traefik
|
||||||
- media
|
- media
|
||||||
volumes:
|
volumes:
|
||||||
- ${TRANSMISSION_CONFIG_DIRECTORY:-/mnt/stingray/media/transmission-openvpn/config}:/config
|
- transmission_config:/config
|
||||||
- ${MEDIA_DIRECTORY:-/mnt/media}/torrents:${MEDIA_DIRECTORY:-/mnt/media}/torrents
|
- ${MEDIA_DIRECTORY:-/mnt/media}/torrents:${MEDIA_DIRECTORY:-/mnt/media}/torrents
|
||||||
environment:
|
environment:
|
||||||
- PUID=${PUID:-8796}
|
- PUID=${PUID:-8796}
|
||||||
@ -43,18 +42,14 @@ services:
|
|||||||
- TRANSMISSION_WEB_UI=flood-for-transmission
|
- TRANSMISSION_WEB_UI=flood-for-transmission
|
||||||
- TZ=America/Vancouver
|
- TZ=America/Vancouver
|
||||||
- LOCAL_NETWORK=10.0.0.0/16
|
- LOCAL_NETWORK=10.0.0.0/16
|
||||||
|
labels:
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.http.routers.transmission_openvpn.rule=Host(`${TRANSMISSION_HOST:-tovpn.jumper.mnke.org}`)"
|
||||||
|
- "traefik.http.routers.transmission_openvpn.entrypoints=websecure"
|
||||||
|
- "traefik.http.routers.transmission_openvpn.tls=true"
|
||||||
|
- "traefik.http.services.transmission_openvpn.loadbalancer.server.port=9091"
|
||||||
|
- "traefik.docker.network=traefik"
|
||||||
deploy:
|
deploy:
|
||||||
labels:
|
|
||||||
- "traefik.enable=true"
|
|
||||||
- "traefik.http.routers.transmission_openvpn.rule=Host(`${TRANSMISSION_HOST:-tovpn.stingray.mnke.org}`)"
|
|
||||||
- "traefik.http.routers.transmission_openvpn.entrypoints=websecure"
|
|
||||||
- "traefik.http.routers.transmission_openvpn.tls.certresolver=letsencrypt"
|
|
||||||
- "traefik.http.services.transmission_openvpn.loadbalancer.server.port=9091"
|
|
||||||
- "traefik.swarm.network=traefik"
|
|
||||||
mode: replicated
|
|
||||||
replicas: 1
|
|
||||||
placement:
|
|
||||||
constraints: [node.role != manager]
|
|
||||||
resources:
|
resources:
|
||||||
limits:
|
limits:
|
||||||
cpus: '0.50'
|
cpus: '0.50'
|
||||||
@ -73,17 +68,15 @@ services:
|
|||||||
- media
|
- media
|
||||||
- traefik
|
- traefik
|
||||||
volumes:
|
volumes:
|
||||||
- ${PROWLARR_CONFIG_DIRECTORY:-/mnt/stingray/media/prowlarr/config}:/config
|
- prowlarr_config:/config
|
||||||
|
labels:
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.http.routers.prowlarr.rule=Host(`${PROWLARR_HOST:-prowlarr.jumper.mnke.org}`)"
|
||||||
|
- "traefik.http.routers.prowlarr.entrypoints=websecure"
|
||||||
|
- "traefik.http.routers.prowlarr.tls=true"
|
||||||
|
- "traefik.http.services.prowlarr.loadbalancer.server.port=9696"
|
||||||
|
- "traefik.docker.network=traefik"
|
||||||
deploy:
|
deploy:
|
||||||
labels:
|
|
||||||
- "traefik.enable=true"
|
|
||||||
- "traefik.http.routers.prowlarr.rule=Host(`${PROWLARR_HOST:-prowlarr.stingray.mnke.org}`)"
|
|
||||||
- "traefik.http.routers.prowlarr.entrypoints=websecure"
|
|
||||||
- "traefik.http.routers.prowlarr.tls.certresolver=letsencrypt"
|
|
||||||
- "traefik.http.services.prowlarr.loadbalancer.server.port=9696"
|
|
||||||
- "traefik.swarm.network=traefik"
|
|
||||||
placement:
|
|
||||||
constraints: [node.role != manager]
|
|
||||||
resources:
|
resources:
|
||||||
limits:
|
limits:
|
||||||
cpus: '0.5'
|
cpus: '0.5'
|
||||||
@ -102,20 +95,20 @@ services:
|
|||||||
- media
|
- media
|
||||||
- traefik
|
- traefik
|
||||||
volumes:
|
volumes:
|
||||||
- ${RADARR_CONFIG_DIRECTORY:-/mnt/stingray/media/radarr/config}:/config
|
- radarr_config:/config
|
||||||
- ${MEDIA_DIRECTORY:-/mnt/media}:${MEDIA_DIRECTORY:-/mnt/media}
|
- ${MEDIA_DIRECTORY:-/mnt/media}:${MEDIA_DIRECTORY:-/mnt/media}
|
||||||
|
depends_on:
|
||||||
|
transmission-openvpn:
|
||||||
|
condition: service_healthy
|
||||||
|
labels:
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.http.routers.radarr.rule=Host(`${RADARR_HOST:-radarr.jumper.mnke.org}`)"
|
||||||
|
- "traefik.http.routers.radarr.entrypoints=websecure"
|
||||||
|
- "traefik.http.routers.radarr.tls=true"
|
||||||
|
- "traefik.http.services.radarr.loadbalancer.server.port=7878"
|
||||||
|
- "traefik.docker.network=traefik"
|
||||||
deploy:
|
deploy:
|
||||||
labels:
|
|
||||||
- "traefik.enable=true"
|
|
||||||
- "traefik.http.routers.radarr.rule=Host(`${RADARR_HOST:-radarr.stingray.mnke.org}`)"
|
|
||||||
- "traefik.http.routers.radarr.entrypoints=websecure"
|
|
||||||
- "traefik.http.routers.radarr.tls.certresolver=letsencrypt"
|
|
||||||
- "traefik.http.services.radarr.loadbalancer.server.port=7878"
|
|
||||||
- "traefik.swarm.network=traefik"
|
|
||||||
mode: replicated
|
mode: replicated
|
||||||
replicas: 1
|
|
||||||
placement:
|
|
||||||
constraints: [node.role != manager]
|
|
||||||
resources:
|
resources:
|
||||||
limits:
|
limits:
|
||||||
cpus: '0.5'
|
cpus: '0.5'
|
||||||
@ -134,20 +127,19 @@ services:
|
|||||||
- media
|
- media
|
||||||
- traefik
|
- traefik
|
||||||
volumes:
|
volumes:
|
||||||
- ${SONARR_CONFIG_DIRECTORY:-/mnt/stingray/media/sonarr/config}:/config
|
- sonarr_config:/config
|
||||||
- ${MEDIA_DIRECTORY:-/mnt/media}:${MEDIA_DIRECTORY:-/mnt/media}
|
- ${MEDIA_DIRECTORY:-/mnt/media}:${MEDIA_DIRECTORY:-/mnt/media}
|
||||||
|
depends_on:
|
||||||
|
transmission-openvpn:
|
||||||
|
condition: service_healthy
|
||||||
|
labels:
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.http.routers.sonarr.rule=Host(`${SONARR_HOST:-sonarr.jumper.mnke.org}`)"
|
||||||
|
- "traefik.http.routers.sonarr.entrypoints=websecure"
|
||||||
|
- "traefik.http.routers.sonarr.tls=true"
|
||||||
|
- "traefik.http.services.sonarr.loadbalancer.server.port=8989"
|
||||||
|
- "traefik.docker.network=traefik"
|
||||||
deploy:
|
deploy:
|
||||||
labels:
|
|
||||||
- "traefik.enable=true"
|
|
||||||
- "traefik.http.routers.sonarr.rule=Host(`${SONARR_HOST:-sonarr.stingray.mnke.org}`)"
|
|
||||||
- "traefik.http.routers.sonarr.entrypoints=websecure"
|
|
||||||
- "traefik.http.routers.sonarr.tls.certresolver=letsencrypt"
|
|
||||||
- "traefik.http.services.sonarr.loadbalancer.server.port=8989"
|
|
||||||
- "traefik.swarm.network=traefik"
|
|
||||||
mode: replicated
|
|
||||||
replicas: 1
|
|
||||||
placement:
|
|
||||||
constraints: [node.role != manager]
|
|
||||||
resources:
|
resources:
|
||||||
limits:
|
limits:
|
||||||
cpus: '0.5'
|
cpus: '0.5'
|
||||||
@ -168,10 +160,6 @@ services:
|
|||||||
# ports:
|
# ports:
|
||||||
# - "${PORT:-8191}:8191"
|
# - "${PORT:-8191}:8191"
|
||||||
deploy:
|
deploy:
|
||||||
mode: replicated
|
|
||||||
replicas: 1
|
|
||||||
placement:
|
|
||||||
constraints: [node.role != manager]
|
|
||||||
resources:
|
resources:
|
||||||
limits:
|
limits:
|
||||||
cpus: '0.25'
|
cpus: '0.25'
|
||||||
@ -183,25 +171,26 @@ services:
|
|||||||
jellyseerr:
|
jellyseerr:
|
||||||
image: fallenbagel/jellyseerr
|
image: fallenbagel/jellyseerr
|
||||||
environment:
|
environment:
|
||||||
- LOG_LEVEL=debug
|
# - LOG_LEVEL=debug
|
||||||
- TZ=America/Vancouver
|
- TZ=America/Vancouver
|
||||||
networks:
|
networks:
|
||||||
- media
|
- media
|
||||||
- traefik
|
- traefik
|
||||||
volumes:
|
volumes:
|
||||||
- ${JELLYSEERR_CONFIG_DIRECTORY:-/mnt/stingray/media/jellyseerr/config}:/app/config
|
- jellyseerr_config:/app/config
|
||||||
|
depends_on:
|
||||||
|
radarr:
|
||||||
|
condition: service_started
|
||||||
|
sonarr:
|
||||||
|
condition: service_started
|
||||||
|
labels:
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.http.routers.jellyseerr.rule=Host(`${JELLYSEERR_HOST:-seerr.jumper.mnke.org}`)"
|
||||||
|
- "traefik.http.routers.jellyseerr.entrypoints=websecure"
|
||||||
|
- "traefik.http.routers.jellyseerr.tls=true"
|
||||||
|
- "traefik.http.services.jellyseerr.loadbalancer.server.port=5055"
|
||||||
|
- "traefik.docker.network=traefik"
|
||||||
deploy:
|
deploy:
|
||||||
labels:
|
|
||||||
- "traefik.enable=true"
|
|
||||||
- "traefik.http.routers.jellyseerr.rule=Host(`${JELLYSEERR_HOST:-seerr.stingray.mnke.org}`)"
|
|
||||||
- "traefik.http.routers.jellyseerr.entrypoints=websecure"
|
|
||||||
- "traefik.http.routers.jellyseerr.tls.certresolver=letsencrypt"
|
|
||||||
- "traefik.http.services.jellyseerr.loadbalancer.server.port=5055"
|
|
||||||
- "traefik.swarm.network=traefik"
|
|
||||||
mode: replicated
|
|
||||||
replicas: 1
|
|
||||||
placement:
|
|
||||||
constraints: [node.role != manager]
|
|
||||||
resources:
|
resources:
|
||||||
limits:
|
limits:
|
||||||
cpus: '0.5'
|
cpus: '0.5'
|
68
docker/compose/traefik/docker-compose.yml
Normal file
68
docker/compose/traefik/docker-compose.yml
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
networks:
|
||||||
|
traefik:
|
||||||
|
attachable: true
|
||||||
|
name: traefik
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
traefik:
|
||||||
|
|
||||||
|
services:
|
||||||
|
traefik:
|
||||||
|
image: traefik:v3.3
|
||||||
|
command:
|
||||||
|
# - "--log.level=DEBUG"
|
||||||
|
- "--api.dashboard=true"
|
||||||
|
- "--api.insecure=true"
|
||||||
|
- "--providers.docker.exposedByDefault=false"
|
||||||
|
- "--providers.docker.endpoint=unix:///var/run/docker.sock"
|
||||||
|
# HTTP
|
||||||
|
- "--entrypoints.web.address=:80"
|
||||||
|
# Redirect to HTTPS
|
||||||
|
- "--entrypoints.web.http.redirections.entrypoint.to=websecure"
|
||||||
|
- "--entrypoints.web.http.redirections.entrypoint.scheme=https"
|
||||||
|
- "--entrypoints.websecure.address=:443"
|
||||||
|
# TLS
|
||||||
|
- "--certificatesresolvers.letsencrypt.acme.dnschallenge=true"
|
||||||
|
- "--certificatesresolvers.letsencrypt.acme.dnschallenge.provider=cloudflare"
|
||||||
|
- "--certificatesresolvers.letsencrypt.acme.dnschallenge.resolvers[0]=1.1.1.1"
|
||||||
|
- "--certificatesresolvers.letsencrypt.acme.dnschallenge.resolvers[1]=1.0.0.1"
|
||||||
|
- "--certificatesresolvers.letsencrypt.acme.caserver=https://acme-v02.api.letsencrypt.org/directory"
|
||||||
|
- "--certificatesresolvers.letsencrypt.acme.email=${CF_EMAIL}"
|
||||||
|
- "--certificatesresolvers.letsencrypt.acme.storage=/data/acme.json"
|
||||||
|
ports:
|
||||||
|
- "80:80"
|
||||||
|
- "443:443"
|
||||||
|
- "8080:8080"
|
||||||
|
environment:
|
||||||
|
- "CF_EMAIL=${CF_EMAIL:-tonydu121@hotmail.com}"
|
||||||
|
- "CF_DNS_API_TOKEN=${CF_DNS_API_TOKEN}"
|
||||||
|
volumes:
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
- traefik:/data
|
||||||
|
networks:
|
||||||
|
- traefik
|
||||||
|
labels:
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.http.routers.api.rule=Host(`traefik.jumper.mnke.org`)"
|
||||||
|
- "traefik.http.routers.api.entrypoints=websecure"
|
||||||
|
- "traefik.http.routers.api.service=api@internal"
|
||||||
|
- "traefik.http.routers.api.middlewares=auth"
|
||||||
|
- "traefik.http.routers.api.tls.certresolver=letsencrypt"
|
||||||
|
- "traefik.http.routers.api.tls.domains[0].main=mnke.org"
|
||||||
|
- "traefik.http.routers.api.tls.domains[0].sans=*.mnke.org"
|
||||||
|
- "traefik.http.routers.api.tls.domains[1].main=jumper.mnke.org"
|
||||||
|
- "traefik.http.routers.api.tls.domains[1].sans=*.jumper.mnke.org"
|
||||||
|
- "traefik.http.middlewares.auth.basicauth.users=${TRAEFIK_HTPASSWD}"
|
||||||
|
- "traefik.http.services.dummy-svc.loadbalancer.server.port=9999"
|
||||||
|
|
||||||
|
whoami:
|
||||||
|
image: "traefik/whoami"
|
||||||
|
networks:
|
||||||
|
- traefik
|
||||||
|
labels:
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.http.routers.whoami.rule=Host(`whoami.jumper.mnke.org`)"
|
||||||
|
- "traefik.http.routers.whoami.entrypoints=websecure"
|
||||||
|
- "traefik.http.routers.whoami.tls=true"
|
||||||
|
- "traefik.http.services.whoami.loadbalancer.server.port=80"
|
||||||
|
- "traefik.docker.network=traefik"
|
@ -4,7 +4,7 @@ locals {
|
|||||||
}
|
}
|
||||||
|
|
||||||
module "dns_server" {
|
module "dns_server" {
|
||||||
source = "${path.module}/modules/dns-server"
|
source = "./modules/dns-server"
|
||||||
|
|
||||||
vm_id = "200"
|
vm_id = "200"
|
||||||
|
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
module "docker_swarm_stingray" {
|
module "docker_swarm_stingray" {
|
||||||
source = "${path.module}/modules/docker-swarm"
|
source = "./modules/docker-swarm"
|
||||||
|
|
||||||
swarm_name = "stingray"
|
swarm_name = "stingray"
|
||||||
vm_id_prefix = "8"
|
vm_id_prefix = "8"
|
||||||
subnet_cidr = "10.0.42.0/24"
|
subnet_cidr = "10.0.42.0/24"
|
||||||
gateway = "10.0.0.1"
|
gateway = var.gateway
|
||||||
manager_count = 3
|
manager_count = 3
|
||||||
worker_count = 3
|
worker_count = 3
|
||||||
dns_server_ip = local.dns_server_ip
|
dns_server_ip = local.dns_server_ip
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
module "k8s_dolo" {
|
module "k8s_dolo" {
|
||||||
source = "${path.module}/modules/k8s"
|
source = "./modules/k8s"
|
||||||
started = true
|
started = true
|
||||||
|
|
||||||
cluster_name = "dolo"
|
cluster_name = "dolo"
|
||||||
vm_id_prefix = "1"
|
vm_id_prefix = "1"
|
||||||
subnet_cidr = "10.0.185.0/24"
|
subnet_cidr = "10.0.185.0/24"
|
||||||
gateway = "10.0.0.1"
|
gateway = var.gateway
|
||||||
control_plane_count = 3
|
control_plane_count = 3
|
||||||
worker_count = 3
|
worker_count = 3
|
||||||
storage_worker_count = 3
|
storage_worker_count = 3
|
||||||
@ -20,7 +20,7 @@ module "k8s_dolo" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
module "k8s_folly" {
|
module "k8s_folly" {
|
||||||
source = "${path.module}/modules/k8s"
|
source = "./modules/k8s"
|
||||||
|
|
||||||
started = false
|
started = false
|
||||||
|
|
||||||
|
115
tf/outpost.tf
Normal file
115
tf/outpost.tf
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
resource "proxmox_virtual_environment_file" "jumper" {
|
||||||
|
content_type = "snippets"
|
||||||
|
datastore_id = var.proxmox_image_storage
|
||||||
|
node_name = "pve"
|
||||||
|
|
||||||
|
source_raw {
|
||||||
|
data = <<EOF
|
||||||
|
${local.common_cloud_init}
|
||||||
|
|
||||||
|
hostname: jumper
|
||||||
|
EOF
|
||||||
|
file_name = "jumper.cloud-config.yaml"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "proxmox_virtual_environment_vm" "jumper_storage_dummy" {
|
||||||
|
name = "jumper-dummy"
|
||||||
|
description = "Managed by Terraform"
|
||||||
|
tags = ["terraform", "disk-dummy"]
|
||||||
|
|
||||||
|
node_name = "pve"
|
||||||
|
vm_id = 7101
|
||||||
|
|
||||||
|
started = false
|
||||||
|
on_boot = false
|
||||||
|
|
||||||
|
disk {
|
||||||
|
datastore_id = var.proxmox_vm_storage
|
||||||
|
file_format = "qcow2"
|
||||||
|
interface = "scsi0"
|
||||||
|
size = 32
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "proxmox_virtual_environment_vm" "jumper" {
|
||||||
|
# Don't forget to change the cloud init file if this is changed
|
||||||
|
name = "jumper"
|
||||||
|
description = "Managed by Terraform"
|
||||||
|
tags = ["terraform", "ubuntu", "outpost"]
|
||||||
|
|
||||||
|
node_name = "pve"
|
||||||
|
vm_id = 7001
|
||||||
|
|
||||||
|
cpu {
|
||||||
|
cores = 4
|
||||||
|
type = "host"
|
||||||
|
}
|
||||||
|
|
||||||
|
memory {
|
||||||
|
dedicated = 4096
|
||||||
|
floating = 4096
|
||||||
|
}
|
||||||
|
|
||||||
|
agent {
|
||||||
|
enabled = true
|
||||||
|
}
|
||||||
|
|
||||||
|
startup {
|
||||||
|
order = "1"
|
||||||
|
up_delay = "60"
|
||||||
|
down_delay = "60"
|
||||||
|
}
|
||||||
|
|
||||||
|
disk {
|
||||||
|
datastore_id = var.proxmox_vm_storage
|
||||||
|
file_id = proxmox_virtual_environment_file.ubuntu_cloud_image.id
|
||||||
|
interface = "virtio0"
|
||||||
|
iothread = true
|
||||||
|
discard = "on"
|
||||||
|
size = 32
|
||||||
|
file_format = "qcow2"
|
||||||
|
}
|
||||||
|
|
||||||
|
initialization {
|
||||||
|
ip_config {
|
||||||
|
ipv4 {
|
||||||
|
address = "10.0.44.2/16"
|
||||||
|
gateway = var.gateway
|
||||||
|
}
|
||||||
|
}
|
||||||
|
datastore_id = var.proxmox_image_storage
|
||||||
|
|
||||||
|
user_data_file_id = proxmox_virtual_environment_file.jumper.id
|
||||||
|
}
|
||||||
|
|
||||||
|
dynamic "disk" {
|
||||||
|
for_each = { for idx, val in proxmox_virtual_environment_vm.jumper_storage_dummy.disk : idx => val }
|
||||||
|
iterator = data_disk
|
||||||
|
content {
|
||||||
|
datastore_id = data_disk.value["datastore_id"]
|
||||||
|
path_in_datastore = data_disk.value["path_in_datastore"]
|
||||||
|
file_format = data_disk.value["file_format"]
|
||||||
|
size = data_disk.value["size"]
|
||||||
|
# assign from scsi1 and up
|
||||||
|
interface = "scsi${data_disk.key + 1}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
network_device {
|
||||||
|
bridge = "vmbr0"
|
||||||
|
}
|
||||||
|
|
||||||
|
operating_system {
|
||||||
|
type = "l26"
|
||||||
|
}
|
||||||
|
|
||||||
|
lifecycle {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "ansible_host" "jumper" {
|
||||||
|
name = "jumper.local"
|
||||||
|
groups = ["jumper", "portainer_agent"]
|
||||||
|
}
|
||||||
|
|
@ -8,6 +8,10 @@ terraform {
|
|||||||
source = "hashicorp/local"
|
source = "hashicorp/local"
|
||||||
version = "2.5.2"
|
version = "2.5.2"
|
||||||
}
|
}
|
||||||
|
ansible = {
|
||||||
|
source = "ansible/ansible"
|
||||||
|
version = "1.3.0"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,10 @@ variable "proxmox_api_token" {
|
|||||||
description = "Proxmox API token bpg proxmox provider with ID and token"
|
description = "Proxmox API token bpg proxmox provider with ID and token"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
variable "gateway" {
|
||||||
|
type = string
|
||||||
|
}
|
||||||
|
|
||||||
variable "s3_backend_endpoint" {
|
variable "s3_backend_endpoint" {
|
||||||
type = string
|
type = string
|
||||||
# example = "http://s3.local"
|
# example = "http://s3.local"
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
proxmox_image_storage = "proxmox-local-directory"
|
proxmox_image_storage = "proxmox-local-directory"
|
||||||
proxmox_vm_storage = "proxmox-local-directory"
|
proxmox_vm_storage = "proxmox-local-directory"
|
||||||
|
gateway = "10.0.0.1"
|
||||||
|
|
||||||
username = "tony"
|
username = "tony"
|
||||||
ssh_import_id = "gh:tonyd33"
|
ssh_import_id = "gh:tonyd33"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user