Compare commits

..

3 Commits
master ... test

Author SHA1 Message Date
Nemo 531b348c08 just run it 2018-05-06 03:18:08 +05:30
Nemo 7108da56a6 just run it 2018-05-06 03:16:41 +05:30
Nemo 8eed15d253 test commit 2018-05-06 03:02:35 +05:30
159 changed files with 1785 additions and 3851 deletions

5
.gitignore vendored
View File

@ -3,11 +3,6 @@
.terraform
*.tfstate
*.tfstate.backup
*.terraform.lock.hcl
*.out
*.backup
secrets
k8s/
k8s2/
docker/conf/wiki.yml
plan

View File

@ -1 +0,0 @@
1.3.6

View File

@ -1,18 +0,0 @@
# Hacking on the thing
Generate certs as per:
https://gist.github.com/captn3m0/2c2e723b2dcd5cdaad733aad12be59a2
Copy ca.pem, server-cert.pem, server-key.pem to /etc/docker/certs.
Make sure server-key.pem is 0400 in permissions.
Run `systemctl edit docker`
````
/etc/systemd/system/docker.service.d/override.conf
[Service]
ExecStart=
ExecStart=/usr/bin/dockerd --tlsverify --tlscacert=/etc/docker/certs/ca.pem --tlscert=/etc/docker/certs/server-cert.pem --tlskey=/etc/docker/certs/server-key.pem -H=0.0.0.0:2376 -H unix:///var/run/docker.sock
````

124
README.md
View File

@ -2,106 +2,102 @@
![Nebula header image](https://cdn.spacetelescope.org/archives/images/thumb700x/heic0707a.jpg)
> Where stars are born.
>Where stars are born.
Manages the local infrastructure of my home server. I'm also doing blog posts around the same:
1. [Part 1, Hardware](https://captnemo.in/blog/2017/09/17/home-server-build/)
2. [Part 2, Terraform/Docker](https://captnemo.in/blog/2017/11/09/home-server-update/)
3. [Part 3, Learnings](https://captnemo.in/blog/2017/12/18/home-server-learnings/)
4. [Part 4, Migrating from Google (and more)](https://captnemo.in/blog/2017/12/31/migrating-from-google/)
5. [Part 5, Networking](https://captnemo.in/blog/2018/04/22/home-server-networking/)
6. [Part 6, RAID](https://captnemo.in/blog/2019/02/24/btrfs-raid-device-replacement-story/)
1. [Part 1, Hardware](https://captnemo.in/blog/2017/09/17/home-server-build/)
2. [Part 2, Terraform/Docker](https://captnemo.in/blog/2017/11/09/home-server-update/)
3. [Part 3, Learnings](https://captnemo.in/blog/2017/12/18/home-server-learnings/)
4. [Part 4, Migrating from Google (and more)](https://captnemo.in/blog/2017/12/31/migrating-from-google/)
5. [Part 5, Networking](https://captnemo.in/blog/2018/04/22/home-server-networking/)
The canonical URL for this repo is https://git.captnemo.in/nemo/nebula/. A mirror is maintained on GitHub at <https://github.com/captn3m0/nebula>
# modules
1. docker: to actually run the services. Catch-all for miscellaneous containers
2. cloudflare: to manage the DNS.
3. mysql: to create mysql users and databases.
4. media: Media related containers (Jackett, Lidarr, Radarr, Sonarr)
5. Monitoring: Monitoring related resources (Cadvisor, Grafana, NodeExporter, Prometheus, Transmission-Exporter)
6. Gitea: Just git.captnemo.in
7. miniflux: RSS Web reader
8. Radicale: CardDav/CalDav webserver
1. docker: to actually run the services. Catch-all for miscellaneous containers
2. cloudflare: to manage the DNS.
3. mysql: to create mysql users and databases.
4. media: Media related containers (Jackett, Lidarr, Radarr, Sonarr)
5. Monitoring: Monitoring related resources (Cadvisor, Grafana, NodeExporter, Prometheus, Transmission-Exporter)
6. Gitea: Just git.captnemo.in
7. tt-rss: Tiny-Tiny RSS Web reader
8. Radicale: CardDav/CalDav webserver
Self-learning project for terraform/docker.
# Planned
1. ~Setup DigitalOcean~
2. Add DO infrastructure via ansible
3. ~Add traefik for proper proxying~
4. Maybe add docker swarm (or k8s?) across both the servers. Might setup the k8s API on the Raspberry Pi.
1. ~Setup DigitalOcean~
2. Add DO infrastructure via ansible
3. ~Add traefik for proper proxying~
4. Maybe add docker swarm (or k8s?) across both the servers. Might setup the k8s API on the Raspberry Pi.
# Service List
Currently running the following (all links are to the `store.docker.com` links for the docker images that I'm using:
| image | tag | module/link |
| -------------------------------- | ---------- | ---------------------------------------------------- |
| captn3m0/opml-gen | latest | https://opml.bb8.fun |
| captn3m0/rss-bridge | latest | https://github.com/RSS-Bridge/rss-bridge |
| captn3m0/speedtest-exporter | alpine | https://github.com/stefanwalther/speedtest-exporter |
| emby/embyserver | latest | https://emby.media |
| gitea/gitea | 1.5.0-rc1 | services |
| google/cadvisor | latest | monitoring |
| grafana/grafana | latest | monitoring |
| jankysolutions/requestbin | latest | tools |
| linuxserver/airsonic | latest | media |
| linuxserver/jackett | latest | media |
| linuxserver/lidarr | latest | media |
| linuxserver/lychee | latest | media |
| linuxserver/radarr | latest | media |
| linuxserver/sonarr | latest | media |
| linuxserver/transmission | latest | media |
| linuxserver/ubooquity | latest | media |
| miniflux/miniflux | 2.0.9 | tools |
| postgres | 10-alpine | database |
| prom/node-exporter | v0.15.2 | monitoring |
| prom/prometheus | latest | monitoring |
| requarks/wiki | latest | services |
| serjs/go-socks5-proxy | latest | tools |
| tocttou/gotviz | latest | na |
| tomsquest/docker-radicale | latest | services |
| traefik | 1.6-alpine | plumbing |
| image | tag | size | category/module |
|--------------------------------|---------|------|-----------------|
| prom/node-exporter | v0.15.2 | 22.8 | monitoring |
| redis | alpine | 27.8 | gitea |
| linuxserver/transmission | latest | 43.9 | media |
| traefik | 1.6 | 51.8 | docker |
| google/cadvisor | latest | 62.2 | monitoring |
| odarriba/timemachine | latest | 77.2 | backup |
| gitea/gitea | 1.4 | 77.4 | gitea |
| linuxserver/heimdall | latest | 101 | general |
| linuxserver/tt-rss | latest | 108 | tt-rss |
| prom/prometheus | latest | 113 | monitoring |
| linuxserver/ubooquity | latest | 114 | docker |
| captn3m0/speedtest-exporter | alpine | 115 | monitoring |
| tomsquest/docker-radicale | latest | 130 | radicale |
| linuxserver/lychee | latest | 154 | lychee |
| linuxserver/resilio-sync | latest | 167 | resilio |
| emby/embyserver | latest | 202 | media |
| linuxserver/airsonic | latest | 239 | media |
| grafana/grafana | latest | 301 | monitoring |
| requarks/wiki | latest | 317 | wiki |
| percona/percona-server-mongodb | latest | 321 | wiki |
| mariadb | 10.3 | 402 | db |
| linuxserver/jackett | latest | 556 | media |
| linuxserver/sonarr | latest | 562 | media |
| linuxserver/radarr | latest | 566 | media |
| linuxserver/lidarr | latest | 574 | media |
## Docker Notes
- Lots of the above images are from the excellent [LinuxServer.io](https://www.linuxserver.io), and they're doing great work :+1:
- Most images are running the latest beta (if available) or stable versions.
- Traefik is running with wildcard certificates.
## Upstream
I've been using this as a contributing opportunity and reporting/fixing issues upstream:
Issues I've faced/reported as a result of this project:
1. Airsonic HTTPS proxying is broken. Reported: https://github.com/airsonic/airsonic/issues/641. Turned out to be a known issue: https://github.com/airsonic/airsonic/issues/594. Now fixed.
2. Traefik docker backend security headers were broken with dashes. I [reported it here](https://github.com/containous/traefik/issues/2493), and fixed by https://github.com/containous/traefik/pull/2496 :white_check_mark:
3. Headphones dies repeatedly with no error logs. Yet-to-report. (Already reported, fails due to classical artists)
4. Terraform doesn't parse mariadb version numbers. Report: https://github.com/terraform-providers/terraform-provider-mysql/issues/6. Filed a [PR to fix](https://github.com/hashicorp/go-version/pull/34) and [to bump the go-version dependency](https://github.com/terraform-providers/terraform-provider-mysql/pull/27) :white_check_mark:
5. `elibsrv` didn't support ebook-convert, only mobigen. PR is at https://github.com/captn3m0/elibsrv/pull/1. Merged to `elibsrv` trunk, will be part of next release.
6. `ubooquity` docker container doesn't let you set admin password: https://github.com/linuxserver/docker-ubooquity/issues/17. (Couldn't reproduce, closed) :white_check_mark:
7. Traefik customresponseheaders can't contain colons on the docker backend: https://github.com/containous/traefik/issues/2517. Fixed with https://github.com/containous/traefik/pull/2509 :white_check_mark:
8. Traefik Security headers don't overwrite upstream headers: https://github.com/containous/traefik/issues/2618 :white_check_mark:
9. Transmission exporter broke with different data types while unmarshalling JSON in go. I filed a PR https://github.com/metalmatze/transmission-exporter/pull/2 :white_check_mark:
1. Airsonic HTTPS proxying is broken. Reported: https://github.com/airsonic/airsonic/issues/641. Turned out to be a known issue: https://github.com/airsonic/airsonic/issues/594. Now fixed.
2. Traefik docker backend security headers were broken with dashes. I [reported it here](https://github.com/containous/traefik/issues/2493), and fixed by https://github.com/containous/traefik/pull/2496 :white_check_mark:
3. Headphones dies repeatedly with no error logs. Yet-to-report. (Already reported, fails due to classical artists)
4. Terraform doesn't parse mariadb version numbers. Report: https://github.com/terraform-providers/terraform-provider-mysql/issues/6. Filed a [PR to fix](https://github.com/hashicorp/go-version/pull/34) and [to bump the go-version dependency](https://github.com/terraform-providers/terraform-provider-mysql/pull/27) :white_check_mark:
5. `elibsrv` didn't support ebook-convert, only mobigen. PR is at https://github.com/captn3m0/elibsrv/pull/1. Merged to `elibsrv` trunk, will be part of next release.
6. `ubooquity` docker container doesn't let you set admin password: https://github.com/linuxserver/docker-ubooquity/issues/17. (Couldn't reproduce, closed) :white_check_mark:
7. Traefik customresponseheaders can't contain colons on the docker backend: https://github.com/containous/traefik/issues/2517. Fixed with https://github.com/containous/traefik/pull/2509 :white_check_mark:
8. Traefik Security headers don't overwrite upstream headers: https://github.com/containous/traefik/issues/2618 :white_check_mark:
9. Transmission exporter broke with different data types while unmarshalling JSON in go. I filed a PR https://github.com/metalmatze/transmission-exporter/pull/2 :white_check_mark:
10. Radarr official docker container was [running a very old `mediainfo`](https://github.com/Radarr/Radarr/issues/2668#issuecomment-376310514). [Filed a fix to upgrade `mediainfo` on the official radarr image](https://github.com/linuxserver/docker-baseimage-mono/pull/3) :white_check_mark:
11. Patched the [speedtest-exporter](https://github.com/stefanwalther/speedtest-exporter/pull/7) to use Alpine and upgraded Node.JS for a smaller updated build.
12. Faced (4) above again because mariadb decided to add `:` in the version response. [Workaround was to force set `--version=10.3-mariadb`](https://git.captnemo.in/nemo/nebula/commit/5f47a08bb55eea2c708c41668657ac1efa84c72a)
13. Reported [2 critical security issues in Abstruse CI](https://github.com/bleenco/abstruse/issues/363). :white_check_mark:
14. Faced (13) above again with postgres, thankfully [someone already fixed version parsing](https://github.com/terraform-providers/terraform-provider-postgresql/pull/31) :white_check_mark:
15. RSS Bridge was missing an official Docker Image. [I Filed a PR](https://github.com/RSS-Bridge/rss-bridge/pull/720) :white_check_mark:
# Plumbing
Their is a lot of additional infrastructure that is _not-yet_ part of this repo. This includes:
1. The Digital Ocean droplet running DNSCrypt and simpleproxy to proxy over a openvpn connection to this box.
2. openbox, kodi configuration to run on boot along with the Steam Controller for the HTPC setup
3. Docker main configuration with half-baked CA setup
4. btrfs-backed subvolumes and snapshotting for most things in /mnt/xwing/ (in-progress)
5. User-creation on the main server. (I'm using a common user for media applications and specific users for other applications)
1. The Digital Ocean droplet running DNSCrypt and simpleproxy to proxy over a openvpn connection to this box.
2. openbox, kodi configuration to run on boot along with the Steam Controller for the HTPC setup
3. Docker main configuration with half-baked CA setup
4. btrfs-backed subvolumes and snapshotting for most things in /mnt/xwing/ (in-progress)
5. User-creation on the main server. (I'm using a common user for media applications and specific users for other applications)
# License

View File

@ -1,5 +0,0 @@
<?php
// Generates the Ubooquity preferences.json file
$template = "ubooquity.tpl.json";

33
abstruse/main.tf Normal file
View File

@ -0,0 +1,33 @@
data "docker_registry_image" "abstruse" {
name = "bleenco/abstruse:latest"
}
resource "docker_image" "abstruse" {
name = "${data.docker_registry_image.abstruse.name}"
pull_triggers = ["${data.docker_registry_image.abstruse.sha256_digest}"]
}
resource "docker_container" "abstruse" {
name = "abstruse"
image = "${docker_image.abstruse.latest}"
labels = "${merge(
var.traefik-labels, map(
"traefik.port", 6500,
"traefik.frontend.rule","Host:${var.domain}"
))}"
volumes {
host_path = "/var/run/docker.sock"
container_path = "/var/run/docker.sock"
}
volumes {
host_path = "/mnt/xwing/config/abstruse"
container_path = "/root/.abstruse"
}
restart = "unless-stopped"
destroy_grace_seconds = 60
must_run = true
}

7
abstruse/variables.tf Normal file
View File

@ -0,0 +1,7 @@
variable "domain" {
description = "domain to be used by traefik"
}
variable "traefik-labels" {
type = "map"
}

View File

@ -4,18 +4,18 @@
*/
resource "cloudflare_record" "home" {
zone_id = var.zone_id
name = "in"
value = var.ips["eth0"]
type = "A"
domain = "${var.domain}"
name = "in"
value = "${var.ips["eth0"]}"
type = "A"
}
resource "cloudflare_record" "home-wildcard" {
zone_id = var.zone_id
name = "*.in"
value = cloudflare_record.home.hostname
type = "CNAME"
ttl = 3600
domain = "${var.domain}"
name = "*.in"
value = "${cloudflare_record.home.hostname}"
type = "CNAME"
ttl = 3600
}
/**
@ -23,42 +23,26 @@ resource "cloudflare_record" "home-wildcard" {
* *.bb8.fun -> bb8.fun
*/
resource "cloudflare_record" "internet" {
zone_id = var.zone_id
name = "@"
value = var.droplet_ip
type = "A"
domain = "${var.domain}"
name = "@"
value = "${var.ips["static"]}"
type = "A"
}
resource "cloudflare_record" "internet-wildcard" {
zone_id = var.zone_id
name = var.domain
value = cloudflare_record.internet.hostname
type = "CNAME"
ttl = 3600
domain = "${var.domain}"
name = "*.${var.domain}"
value = "${cloudflare_record.internet.hostname}"
type = "CNAME"
ttl = 3600
}
resource "cloudflare_record" "dns" {
zone_id = var.zone_id
name = "dns"
value = var.ips["static"]
type = "A"
}
resource "cloudflare_record" "doh" {
zone_id = var.zone_id
name = "doh"
value = var.ips["static"]
type = "A"
}
// This ensures that _acme-challenge is not a CNAME
// alongside the above wildcard CNAME entry.
resource "cloudflare_record" "acme-no-cname-1" {
zone_id = var.zone_id
name = "_acme-challenge.${var.domain}"
type = "A"
value = "127.0.0.1"
ttl = "300"
domain = "${var.domain}"
name = "_acme-challenge.${var.domain}"
type = "A"
value = "127.0.0.1"
ttl = "300"
}
/**
@ -66,44 +50,18 @@ resource "cloudflare_record" "acme-no-cname-1" {
* *.vpn.bb8.fun
*/
resource "cloudflare_record" "vpn" {
zone_id = var.zone_id
name = "vpn"
value = var.ips["tun0"]
type = "A"
domain = "${var.domain}"
name = "vpn"
value = "${var.ips["tun0"]}"
type = "A"
}
resource "cloudflare_record" "vpn_wildcard" {
zone_id = var.zone_id
name = "*.vpn.${var.domain}"
value = cloudflare_record.vpn.hostname
type = "CNAME"
ttl = 3600
}
/**
* vpn.bb8.fun
* *.vpn.bb8.fun
*/
resource "cloudflare_record" "dovpn" {
zone_id = var.zone_id
name = "dovpn"
value = var.ips["dovpn"]
type = "A"
}
resource "cloudflare_record" "dovpn_wildcard" {
zone_id = var.zone_id
name = "*.dovpn.${var.domain}"
value = cloudflare_record.dovpn.hostname
type = "CNAME"
ttl = 3600
}
resource "cloudflare_record" "etcd" {
zone_id = var.zone_id
name = "etcd"
value = var.ips["dovpn"]
type = "A"
domain = "${var.domain}"
name = "*.vpn.${var.domain}"
value = "${cloudflare_record.vpn.hostname}"
type = "CNAME"
ttl = 3600
}
########################
@ -111,21 +69,21 @@ resource "cloudflare_record" "etcd" {
########################
resource "cloudflare_record" "mailgun-spf" {
zone_id = var.zone_id
name = "l"
value = "v=spf1 include:mailgun.org ~all"
type = "TXT"
domain = "${var.domain}"
name = "l"
value = "v=spf1 include:mailgun.org ~all"
type = "TXT"
}
resource "cloudflare_record" "mailgun-dkim" {
zone_id = var.zone_id
name = "k1._domainkey.l"
value = "k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCnbP+IQkuPkgmUhpqCKzIdDSZ0HazaMp+cdBH++LBed8oY8/jmV8BhxMp5JwyePzRTxneT8ASsRtcp7CQ3z4nMC7aFX0kH6Bnu2v+u2JWudxs8x0I02OrPbSaQ5QVQdbAaCUCEfCQ06LJsn8aqPNrRIOWEMnxln+ebFJ0wKGscFQIDAQAB"
type = "TXT"
domain = "${var.domain}"
name = "k1._domainkey.l"
value = "k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCnbP+IQkuPkgmUhpqCKzIdDSZ0HazaMp+cdBH++LBed8oY8/jmV8BhxMp5JwyePzRTxneT8ASsRtcp7CQ3z4nMC7aFX0kH6Bnu2v+u2JWudxs8x0I02OrPbSaQ5QVQdbAaCUCEfCQ06LJsn8aqPNrRIOWEMnxln+ebFJ0wKGscFQIDAQAB"
type = "TXT"
}
resource "cloudflare_record" "mailgun-mxa" {
zone_id = var.zone_id
domain = "${var.domain}"
name = "l"
value = "mxa.mailgun.org"
type = "MX"
@ -133,17 +91,17 @@ resource "cloudflare_record" "mailgun-mxa" {
}
resource "cloudflare_record" "mailgun-mxb" {
zone_id = var.zone_id
domain = "${var.domain}"
name = "l"
value = "mxb.mailgun.org"
type = "MX"
priority = 20
}
resource "cloudflare_record" "k8s" {
zone_id = var.zone_id
name = "k8s"
value = "10.8.0.1"
type = "A"
ttl = 3600
resource "cloudflare_record" "k8s-talk" {
domain = "${var.domain}"
name = "k8s"
value = "lightsaber.captnemo.in"
type = "CNAME"
ttl = 3600
}

View File

@ -1,7 +0,0 @@
terraform {
required_providers {
cloudflare = {
source = "cloudflare/cloudflare"
}
}
}

View File

@ -1,10 +1,7 @@
variable "domain" {
type = string
type = "string"
}
variable "ips" {
type = map
type = "map"
}
variable "droplet_ip" {}
variable "zone_id" {}

11
data.tf
View File

@ -1,11 +0,0 @@
data "docker_network" "bridge" {
name = "bridge"
}
data "cloudflare_zones" "bb8" {
filter {
name = "bb8"
lookup_type = "exact"
match = "bb8.fun"
}
}

View File

@ -1,10 +0,0 @@
resource "docker_network" "postgres" {
name = "postgres"
driver = "bridge"
internal = true
ipam_config {
subnet = "172.20.0.8/27"
gateway = "172.20.0.9"
}
}

View File

@ -1,4 +0,0 @@
output "postgres-network-id" {
value = docker_network.postgres.name
}

View File

@ -1,58 +0,0 @@
resource "docker_container" "postgres" {
name = "postgres"
image = docker_image.postgres.image_id
command = [
"postgres",
"-c",
"max_connections=250",
"-c",
"shared_buffers=500MB",
]
volumes {
volume_name = docker_volume.pg_data.name
container_path = "/var/lib/postgresql/data"
read_only = false
}
// This is so that other host-only services can share this
ports {
internal = 5432
external = 5432
ip = var.ips["eth0"]
}
// This is a not-so-great idea
// TODO: Figure out a better way to make terraform SSH and then connect to localhost
ports {
internal = 5432
external = 5432
ip = var.ips["tun0"]
}
memory = 2048
memory_swap = 2048
restart = "unless-stopped"
destroy_grace_seconds = 10
must_run = true
env = [
"POSTGRES_PASSWORD=${var.postgres-root-password}",
]
networks = [docker_network.postgres.id, data.docker_network.bridge.id]
}
resource "docker_image" "postgres" {
name = data.docker_registry_image.postgres.name
pull_triggers = [data.docker_registry_image.postgres.sha256_digest]
}
data "docker_registry_image" "postgres" {
name = "postgres:${var.postgres-version}"
}
data "docker_network" "bridge" {
name = "bridge"
}

View File

@ -1,10 +0,0 @@
terraform {
required_providers {
postgresql = {
source = "cyrilgdn/postgresql"
}
docker = {
source = "kreuzwerker/docker"
}
}
}

View File

@ -1,11 +0,0 @@
variable "postgres-version" {
description = "postgres version to use for fetching the docker image"
default = "14-alpine"
}
variable "ips" {
type = map(string)
}
variable "postgres-root-password" {
}

View File

@ -1,3 +0,0 @@
resource "docker_volume" "pg_data" {
name = "pg_data"
}

View File

@ -1,14 +1,12 @@
resource "digitalocean_droplet" "sydney" {
image = "??"
image = ""
name = "sydney.captnemo.in"
region = "blr1"
size = "s-1vcpu-2gb"
size = "1gb"
ipv6 = true
private_networking = true
resize_disk = true
volume_ids = ["eae03502-9279-11e8-ab31-0242ac11470b"]
tags = [
"bangalore",
"proxy",
@ -16,8 +14,3 @@ resource "digitalocean_droplet" "sydney" {
"vpn",
]
}
output "droplet_ipv4" {
value = digitalocean_droplet.sydney.ipv4_address
}

View File

@ -1,35 +1,38 @@
resource "digitalocean_firewall" "web" {
name = "web-inbound"
inbound_rule {
protocol = "tcp"
port_range = "80"
source_addresses = ["0.0.0.0/0", "::/0"]
}
inbound_rule {
protocol = "tcp"
port_range = "443"
source_addresses = ["0.0.0.0/0", "::/0"]
}
inbound_rule = [
{
protocol = "tcp"
port_range = "80"
source_addresses = ["0.0.0.0/0", "::/0"]
},
{
protocol = "tcp"
port_range = "443"
source_addresses = ["0.0.0.0/0", "::/0"]
},
]
}
resource "digitalocean_firewall" "ssh" {
name = "ssh-inbound"
inbound_rule {
protocol = "tcp"
port_range = "22"
source_addresses = ["0.0.0.0/0", "::/0"]
}
inbound_rule {
protocol = "tcp"
port_range = "222"
source_addresses = ["0.0.0.0/0", "::/0"]
}
inbound_rule {
protocol = "tcp"
port_range = "24"
source_addresses = ["0.0.0.0/0", "::/0"]
}
inbound_rule = [
{
protocol = "tcp"
port_range = "22"
source_addresses = ["0.0.0.0/0", "::/0"]
},
{
protocol = "tcp"
port_range = "222"
source_addresses = ["0.0.0.0/0", "::/0"]
},
{
protocol = "tcp"
port_range = "24"
source_addresses = ["0.0.0.0/0", "::/0"]
},
]
}

View File

@ -1,5 +1,4 @@
resource "digitalocean_floating_ip" "sydney" {
droplet_id = digitalocean_droplet.sydney.id
region = digitalocean_droplet.sydney.region
droplet_id = "${digitalocean_droplet.sydney.id}"
region = "${digitalocean_droplet.sydney.region}"
}

View File

@ -1,19 +0,0 @@
terraform {
required_providers {
pass = {
source = "camptocamp/pass"
}
digitalocean = {
source = "digitalocean/digitalocean"
}
postgresql = {
source = "cyrilgdn/postgresql"
}
cloudflare = {
source = "cloudflare/cloudflare"
}
docker = {
source = "kreuzwerker/docker"
}
}
}

View File

@ -1,72 +0,0 @@
# Web must be converted manually. See https://docs.traefik.io/operations/api/
# Redirect on entry point "http" must be converted manually. See https://docs.traefik.io/middlewares/http/redirectscheme/
# TLS on entry point "https" must be converted manually. See https://docs.traefik.io/routing/routers/#tls
# The domain (bb8.fun) defined in the Docker provider must be converted manually. See https://docs.traefik.io/providers/docker/#defaultrule
# All the elements related to dynamic configuration (backends, frontends, ...) must be converted manually. See https://docs.traefik.io/routing/overview/
# The entry point (https) defined in the ACME configuration must be converted manually. See https://docs.traefik.io/routing/routers/#certresolver
[global]
sendAnonymousUsage = true
[tls.options]
[tls.options.default]
minVersion = "VersionTLS12"
[[tls.certificates]]
certFile = "/etc/traefik/git.captnemo.in.crt"
keyFile = "/etc/traefik/git.captnemo.in.key"
[[tls.certificates]]
certFile = "/etc/traefik/rss.captnemo.in.crt"
keyFile = "/etc/traefik/rss.captnemo.in.key"
# This forces port 8080
[api]
# https://doc.traefik.io/traefik/operations/dashboard/#insecure-mode
dashboard = true
# Enable the API in insecure mode, which means that the API will be available directly on the entryPoint named traefik.
insecure = true
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.http.http]
[entryPoints.https]
address = ":443"
[entryPoints.https.http]
[providers]
providersThrottleDuration = "2s"
[providers.docker]
watch = true
endpoint = "unix:///var/run/docker.sock"
swarmModeRefreshSeconds = "15s"
httpClientTimeout = "0s"
[providers.file]
[log]
[accessLog]
bufferingSize = 0
[certificatesResolvers]
[certificatesResolvers.default]
[certificatesResolvers.default.acme]
email = "acme@captnemo.in"
storage = "/acme/acme.json"
certificatesDuration = 0
[certificatesResolvers.default.acme.dnsChallenge]
provider = "cloudflare"
delayBeforeCheck = "2m0s"
[certificatesResolvers.default.acme.httpChallenge]
entryPoint = "http"
[certificatesResolvers.t]
[certificatesResolvers.t.acme]
email = "acme@captnemo.in"
storage = "/acme/acme.json"
[certificatesResolvers.myresolver.acme.tlsChallenge]
[http.middlewares]
[http.middlewares.test-redirectscheme.redirectScheme]
scheme = "https"
permanent = true

View File

@ -1,26 +0,0 @@
global:
sendAnonymousUsage: true
entryPoints:
http:
address: :80
https:
address: :443
providers:
providersThrottleDuration: 2s
docker:
watch: true
endpoint: unix:///var/run/docker.sock
swarmModeRefreshSeconds: 15s
file: {}
log: {}
accessLog: {}
certificatesResolvers:
default:
acme:
email: acme@captnemo.in
storage: /acme/acme.json
dnsChallenge:
provider: cloudflare
delayBeforeCheck: 2m0s
httpChallenge:
entryPoint: http

View File

@ -1,4 +1,7 @@
defaultEntryPoints = ["http", "https"]
# Have to enable this because of heimdall
InsecureSkipVerify = true
sendAnonymousUsage = true
checkNewVersion = false
@ -6,6 +9,10 @@ checkNewVersion = false
[accessLog]
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.http.redirect]
entryPoint = "https"
[entryPoints.https]
address = ":443"
# This is required for ACME support
@ -16,15 +23,13 @@ checkNewVersion = false
[[entryPoints.https.tls.certificates]]
certFile = "/etc/traefik/rss.captnemo.in.crt"
keyFile = "/etc/traefik/rss.captnemo.in.key"
# This contains 2 domains: {emby|airsonic}.bb8.fun
[[entryPoints.https.tls.certificates]]
certFile = "/etc/traefik/tatooine.club.crt"
keyFile = "/etc/traefik/tatooine.club.key"
certFile = "/etc/traefik/emby.in.bb8.fun.crt"
keyFile = "/etc/traefik/emby.in.bb8.fun.key"
[docker]
# Make sure you mount this as readonly
# NOTE: readonly doesn't reduce the risk because
# it is a unix socket - it doesn't automatically translate
# read|write perms to GET/POST requests.
endpoint = "unix:///var/run/docker.sock"
domain = "bb8.fun"
watch = true
@ -37,6 +42,33 @@ checkNewVersion = false
# Since I can't apply a authentication
# on this yet
[backends.elibsrv]
[backends.elibsrv.servers.default]
url = "http://elibsrv.captnemo.in:90"
[backends.scan]
[backends.scan.servers.default]
url = "http://scan.in.bb8.fun:90"
[frontends]
[frontends.scan]
backend = "scan"
[frontends.scan.headers]
SSLRedirect = true
SSLTemporaryRedirect = true
STSSeconds = 2592000
FrameDeny = true
ContentTypeNosniff = true
BrowserXssFilter = true
ReferrerPolicy = "no-referrer"
[frontends.scan.headers.customresponseheaders]
X-Powered-By = "Allomancy"
Server = "BlackBox"
X-Clacks-Overhead = "GNU Terry Pratchett"
[frontends.scan.routes.domain]
rule = "Host:scan.bb8.fun"
[web]
address = ":1111"
readOnly = true
@ -57,8 +89,7 @@ acmelogging = true
[acme.dnsChallenge]
provider = "cloudflare"
delayBeforeCheck = 120
resolvers = ["1.1.1.1:53", "8.8.8.8:53"]
delayBeforeCheck = 30
# Primary 2 wildcard certs
[[acme.domains]]

View File

@ -10,17 +10,17 @@
"bind-address-ipv6": "::",
"blocklist-enabled": true,
"blocklist-url": "http://john.bitsurge.net/public/biglist.p2p.gz",
"cache-size-mb": 256,
"cache-size-mb": 16,
"dht-enabled": true,
"download-dir": "/downloads",
"download-queue-enabled": false,
"download-queue-enabled": true,
"download-queue-size": 5,
"encryption": 1,
"idle-seeding-limit": 30,
"idle-seeding-limit-enabled": false,
"incomplete-dir": "/downloads",
"incomplete-dir-enabled": true,
"lpd-enabled": true,
"lpd-enabled": false,
"message-level": 2,
"peer-congestion-algorithm": "",
"peer-id-ttl-hours": 6,
@ -31,13 +31,13 @@
"peer-port-random-low": 49152,
"peer-port-random-on-start": false,
"peer-socket-tos": "default",
"pex-enabled": false,
"pex-enabled": true,
"port-forwarding-enabled": true,
"preallocation": 1,
"prefetch-enabled": true,
"queue-stalled-enabled": false,
"queue-stalled-enabled": true,
"queue-stalled-minutes": 30,
"ratio-limit": 1.2,
"ratio-limit": 0.2,
"ratio-limit-enabled": true,
"rename-partial-files": true,
"rpc-host-whitelist": "transmission.bb8.fun,transmission",
@ -51,19 +51,19 @@
"rpc-username": "",
"rpc-whitelist": "127.0.0.1",
"rpc-whitelist-enabled": false,
"scrape-paused-torrents-enabled": false,
"scrape-paused-torrents-enabled": true,
"script-torrent-done-enabled": false,
"script-torrent-done-filename": "",
"seed-queue-enabled": true,
"seed-queue-size": 50,
"seed-queue-enabled": false,
"seed-queue-size": 10,
"speed-limit-down": 100,
"speed-limit-down-enabled": false,
"speed-limit-up": 50,
"speed-limit-up-enabled": false,
"speed-limit-up-enabled": true,
"start-added-torrents": true,
"trash-original-torrent-files": false,
"umask": 2,
"upload-slots-per-torrent": 10,
"upload-slots-per-torrent": 14,
"utp-enabled": true,
"watch-dir": "/watch",
"watch-dir-enabled": true

View File

@ -3,22 +3,12 @@
{
"pathString": "/files",
"userName": [
"arvind",
"diya",
"gappan",
"himanshu",
"konarak",
"pratyush",
"reddit",
"riccu",
"sankalp",
"shreyas",
"tatooine",
"vignesh",
"harman",
"pranav",
"swapnil",
"noopur"
"sankalp",
"riccu",
"pratyush",
"harman"
]
}
],
@ -26,22 +16,13 @@
{
"pathString": "/comics",
"userName": [
"arvind",
"diya",
"gappan",
"himanshu",
"konarak",
"pratyush",
"reddit",
"riccu",
"sankalp",
"shreyas",
"tatooine",
"vignesh",
"harman",
"pranav",
"swapnil",
"noopur"
"sankalp",
"riccu",
"pratyush",
"arvind",
"harman"
]
}
],
@ -49,139 +30,76 @@
{
"pathString": "/books",
"userName": [
"arvind",
"diya",
"gappan",
"himanshu",
"konarak",
"pratyush",
"reddit",
"riccu",
"sankalp",
"shreyas",
"tatooine",
"vignesh",
"harman",
"pranav",
"swapnil",
"noopur"
"sankalp",
"riccu",
"pratyush",
"arvind",
"harman"
]
}
],
"users": [
{
"name": "reddit",
"passwordHash":
"396731fff7f1931aeba6e69d3443d5ef7971569e3b9d64a3a4deca655789917a"
"passwordHash": "396731fff7f1931aeba6e69d3443d5ef7971569e3b9d64a3a4deca655789917a"
},
{
"name": "tatooine",
"passwordHash":
"ca0c540641a9e34c47cbd1866443ca181202aaa422fcc5ad4cbf75095aab7da0"
"passwordHash": "ca0c540641a9e34c47cbd1866443ca181202aaa422fcc5ad4cbf75095aab7da0"
},
{
"name": "riccu",
"passwordHash":
"ff66d15e21624763cb2d65a21a7aa275ae65219d6f5ed0e5c5583c9be2fc3b12"
"passwordHash": "ff66d15e21624763cb2d65a21a7aa275ae65219d6f5ed0e5c5583c9be2fc3b12"
},
{
"name": "sankalp",
"passwordHash":
"b3c219dffa8a379c4daaed75c63141ebefa2a6f0a872e9cd7f328ad6511fb863"
"passwordHash": "b3c219dffa8a379c4daaed75c63141ebefa2a6f0a872e9cd7f328ad6511fb863"
},
{
"name": "pratyush",
"passwordHash":
"e63af1a184949abfd3666ef2c60c462191619fdcefadf9021a5d24f236d302fe"
"passwordHash": "e63af1a184949abfd3666ef2c60c462191619fdcefadf9021a5d24f236d302fe"
},
{
"name": "arvind",
"passwordHash":
"126f31712138ea8e5f77c0e2565be848ec87a4057dfe1c4070a6c9d1f3de8ded"
"passwordHash": "126f31712138ea8e5f77c0e2565be848ec87a4057dfe1c4070a6c9d1f3de8ded"
},
{
"name": "harman",
"passwordHash":
"f9bd71d0a8cee05a724efae4f5636123f18d8c9c531c470892f8681375726bd2"
},
{
"name": "shreyas",
"passwordHash":
"ee4501f0aa63453f4360e974c3220c2c7a4c58d2125d989b80ef855e1471535d"
},
{
"name": "himanshu",
"passwordHash":
"c8da693b24c20921b16a55b8bd21b9e0c76e3bdfba81df20f1a0e6b010e0c3a5"
},
{
"name": "diya",
"passwordHash":
"96d39fafe6c1cfb8504ba8f438ab3e11a972f7a3bb3908287b9e3fa5bd28e19a"
},
{
"name": "vignesh",
"passwordHash":
"a1589cab7d5123af4fb19ccaea31e586348756944b1dca759a16a4a0b8e1243d"
},
{
"name": "konarak",
"passwordHash":
"49afa1013d2be0498107e12fc755f27edb90787161f00a2ef579bb6ad8c59b63"
},
{
"name": "gappan",
"passwordHash":
"681825c273d75dce4151f6c61358038e099fec2c3540369267f1fa28d607ce1d"
},
{
"name": "swapnil",
"passwordHash":
"f916f120f09ec561ff1d76e19e2749d1a6078e92051f1f5fcca884489fd43745"
},
{
"name": "noopur",
"passwordHash":
"f49e49db9893a187773fb08e8671ff2f9cd83b8d43b657fbf0abe67b3dfc0e9d"
},
{
"name": "pranav",
"passwordHash":
"9df97ced8b4de090c469244230ca64f5164ff37e9fde2314cf8c2e87db6d033b"
"passwordHash": "f9bd71d0a8cee05a724efae4f5636123f18d8c9c531c470892f8681375726bd2"
}
],
"isFilesProviderEnabled" : true,
"isComicsProviderEnabled" : true,
"isBooksProviderEnabled" : true,
"isUserManagementEnabled" : true,
"libraryPortNumber" : 2202,
"adminPortNumber" : 2203,
"comicWidth" : 160,
"comicHeight" : 230,
"comicsPaginationNumber" : 30,
"bookWidth" : 160,
"bookHeight" : 230,
"booksPaginationNumber" : 30,
"minimizeToTray" : false,
"minimizeOnStartup" : false,
"autoscanPeriod" : 1440,
"isRemoteAdminEnabled" : true,
"theme" : "default",
"isShrinkingCacheEnabled" : false,
"shrunkPageWidth" : 1536,
"shrunkPageHeight" : 2500,
"shrinkingCachePath" : "",
"autoScanAtLaunch" : false,
"reverseProxyPrefix" : "",
"keystorePath" : "",
"keystorePassword" : "",
"isOpdsProviderEnabled" : true,
"folderExclusionPattern" : "",
"bypassSingleRootFolder" : false,
"enableFolderMetadataDisplay" : true,
"bookmarkUsingCookies" : false,
"displayTitleInsteadOfFileName" : true,
"keepUnreachableSharedFolders" : false,
"isCalibreLibrary" : false,
"instanceId" : "3a0e4425a8e14c719ca2eb382f85292e"
"isFilesProviderEnabled": true,
"isComicsProviderEnabled": true,
"isBooksProviderEnabled": true,
"isUserManagementEnabled": true,
"libraryPortNumber": 2202,
"adminPortNumber": 2203,
"comicWidth": 160,
"comicHeight": 230,
"comicsPaginationNumber": 30,
"bookWidth": 160,
"bookHeight": 230,
"booksPaginationNumber": 30,
"minimizeToTray": false,
"minimizeOnStartup": false,
"autoscanPeriod": 0,
"isRemoteAdminEnabled": true,
"theme": "default",
"isShrinkingCacheEnabled": false,
"shrunkPageWidth": 1536,
"shrunkPageHeight": 2500,
"shrinkingCachePath": "",
"autoScanAtLaunch": false,
"reverseProxyPrefix": "",
"keystorePath": "",
"keystorePassword": "",
"isOpdsProviderEnabled": true,
"folderExclusionPattern": "",
"bypassSingleRootFolder": false,
"enableFolderMetadataDisplay": true,
"bookmarkUsingCookies": false,
"displayTitleInsteadOfFileName": true,
"keepUnreachableSharedFolders": false
}

View File

@ -1,15 +0,0 @@
port: 3000
db:
type: postgres
host: postgres
port: 5432
user: wikijs
db: wikijs
pass: ${DB_PASSWORD}
ssl:
enabled: false
bindIP: 0.0.0.0
logLevel: silly
offline: true
ha: false
dataPath: /data

141
docker/conf/wiki.yml Normal file
View File

@ -0,0 +1,141 @@
#######################################################################
# Wiki.js - CONFIGURATION #
#######################################################################
# Full explanation + examples in the documentation:
# https://docs.requarks.io/wiki/install
# You can use an ENV variable by using $(ENV_VAR_NAME) as the value
# ---------------------------------------------------------------------
# Title of this site
# ---------------------------------------------------------------------
title: Scarif Wiki
# ---------------------------------------------------------------------
# Full public path to the site, without the trailing slash
# ---------------------------------------------------------------------
# INCLUDE CLIENT PORT IF NOT 80/443!
host: https://wiki.bb8.fun
# ---------------------------------------------------------------------
# Port the main server should listen to (80 by default)
# ---------------------------------------------------------------------
# To use process.env.PORT, comment the line below:
port: 9999
# ---------------------------------------------------------------------
# Data Directories
# ---------------------------------------------------------------------
paths:
repo: /repo
data: /data
# ---------------------------------------------------------------------
# Upload Limits
# ---------------------------------------------------------------------
# In megabytes (MB)
uploads:
maxImageFileSize: 5
maxOtherFileSize: 100
# ---------------------------------------------------------------------
# Site Language
# ---------------------------------------------------------------------
# Possible values: en, de, es, fa, fr, ja, ko, nl, pt, ru, sr, tr or zh
lang: en
# Enable for right to left languages (e.g. arabic):
langRtl: false
# ---------------------------------------------------------------------
# Site Authentication
# ---------------------------------------------------------------------
public: true
auth:
defaultReadAccess: false
local:
enabled: true
google:
enabled: false
clientId: GOOGLE_CLIENT_ID
clientSecret: GOOGLE_CLIENT_SECRET
# ---------------------------------------------------------------------
# Secret key to use when encrypting sessions
# ---------------------------------------------------------------------
# Use a long and unique random string (256-bit keys are perfect!)
sessionSecret: $(SESSION_SECRET)
# ---------------------------------------------------------------------
# Database Connection String
# ---------------------------------------------------------------------
db: mongodb://mongorocks:27017/wiki
# ---------------------------------------------------------------------
# Git Connection Info
# ---------------------------------------------------------------------
# git:
# url: https://github.com/Organization/Repo
# branch: master
# auth:
# # Type: basic or ssh
# type: ssh
# # Only for Basic authentication:
# username: marty
# password: MartyMcFly88
# # Only for SSH authentication:
# privateKey: /etc/wiki/keys/git.pem
# sslVerify: true
# # Default email to use as commit author
# serverEmail: marty@example.com
# # Whether to use user email as author in commits
# showUserEmail: true
# ---------------------------------------------------------------------
# Features
# ---------------------------------------------------------------------
# You can enable / disable specific features below
features:
linebreaks: true
mathjax: false
# ---------------------------------------------------------------------
# External Logging
# ---------------------------------------------------------------------
externalLogging:
bugsnag: false
loggly: false
papertrail: false
rollbar: false
sentry: false
# ---------------------------------------------------------------------
# Color Theme
# ---------------------------------------------------------------------
theme:
primary: indigo
alt: blue-grey
viewSource: all # all | write | false
footer: blue-grey
code:
dark: true
colorize: true

View File

@ -1,12 +1,40 @@
# Database versions shouldn't be upgraded
data "docker_registry_image" "mariadb" {
name = "mariadb:${var.mariadb-version}"
}
data "docker_registry_image" "percona-mongodb-server" {
name = "percona/percona-server-mongodb:3.4"
}
data "docker_registry_image" "traefik" {
name = "traefik:1.7"
# Critical and I like upgrading it
# for updating config for new features
name = "traefik:1.6.0-rc5-alpine"
}
# YOLO everything else
data "docker_registry_image" "emby" {
name = "emby/embyserver:latest"
}
data "docker_registry_image" "transmission" {
name = "linuxserver/transmission:latest"
}
data "docker_registry_image" "wikijs" {
name = "requarks/wiki:latest"
}
data "docker_registry_image" "ubooquity" {
name = "linuxserver/ubooquity:latest"
}
data "docker_registry_image" "headerdebug" {
name = "brndnmtthws/nginx-echo-headers:latest"
}
data "docker_registry_image" "lychee" {
name = "linuxserver/lychee:latest"
}

61
docker/db.tf Normal file
View File

@ -0,0 +1,61 @@
resource "docker_container" "mongorocks" {
name = "mongorocks"
image = "${docker_image.percona-mongodb-server.latest}"
restart = "unless-stopped"
destroy_grace_seconds = 30
must_run = true
memory = 256
volumes {
volume_name = "${docker_volume.mongorocks_data_volume.name}"
container_path = "/data/db"
host_path = "${docker_volume.mongorocks_data_volume.mountpoint}"
}
command = [
"--storageEngine=rocksdb",
"--httpinterface",
"--rest",
"--master",
]
}
resource "docker_container" "mariadb" {
name = "mariadb"
image = "${docker_image.mariadb.latest}"
volumes {
volume_name = "${docker_volume.mariadb_volume.name}"
container_path = "/var/lib/mysql"
host_path = "${docker_volume.mariadb_volume.mountpoint}"
}
// This is so that other host-only services can share this
ports {
internal = 3306
external = 3306
ip = "${var.ips["eth0"]}"
}
// This is a not-so-great idea
// TODO: Figure out a better way to make terraform SSH and then connect to localhost
ports {
internal = 3306
external = 3306
ip = "${var.ips["tun0"]}"
}
memory = 512
restart = "unless-stopped"
destroy_grace_seconds = 10
must_run = true
env = [
"MYSQL_ROOT_PASSWORD=${var.mysql_root_password}",
]
command = [
"--version=${var.mariadb-version}-MariaDB",
]
}

16
docker/debug.tf Normal file
View File

@ -0,0 +1,16 @@
# resource "docker_container" "headerdebug" {
# name = "headerdebug"
# image = "${docker_image.headerdebug.latest}"
# restart = "unless-stopped"
# destroy_grace_seconds = 30
# must_run = true
# memory = 16
# labels = "${merge(
# local.traefik_common_labels,
# map(
# "traefik.frontend.rule", "Host:debug.in.${var.domain},debug.${var.domain}",
# "traefik.port", 8080,
# "traefik.enable", "true",
# ))}"
# }

36
docker/emby.tf Normal file
View File

@ -0,0 +1,36 @@
resource "docker_container" "emby" {
name = "emby"
image = "${docker_image.emby.latest}"
volumes {
host_path = "/mnt/xwing/config/emby"
container_path = "/config"
}
volumes {
host_path = "/mnt/xwing/media"
container_path = "/media"
}
labels = "${merge(
local.traefik_common_labels,
map(
"traefik.frontend.rule", "Host:emby.in.${var.domain},emby.${var.domain}",
"traefik.frontend.passHostHeader", "true",
"traefik.port", 8096,
))}"
memory = 2048
restart = "unless-stopped"
destroy_grace_seconds = 10
must_run = true
# Running as lounge:tatooine
env = [
"APP_USER=lounge",
"APP_UID=1004",
"APP_GID=1003",
"APP_CONFIG=/mnt/xwing/config",
"TZ=Asia/Kolkata",
]
}

View File

@ -1,20 +0,0 @@
data "docker_registry_image" "gotviz" {
name = "tocttou/gotviz:latest"
}
# resource "docker_image" "gotviz" {
# name = "${data.docker_registry_image.gotviz.name}"
# pull_triggers = ["${data.docker_registry_image.gotviz.sha256_digest}"]
# }
# resource "docker_container" "gotviz" {
# name = "gotviz"
# image = "${docker_image.gotviz.image_id}"
# labels = "${merge(
# local.traefik_common_labels, map(
# "traefik.port", 8080,
# "traefik.frontend.rule","Host:got-relationships.${var.domain}"
# ))}"
# restart = "unless-stopped"
# destroy_grace_seconds = 60
# must_run = true
# }

View File

@ -1,14 +1,46 @@
resource "docker_image" "traefik17" {
name = data.docker_registry_image.traefik.name
pull_triggers = [data.docker_registry_image.traefik.sha256_digest]
resource "docker_image" "emby" {
name = "${data.docker_registry_image.emby.name}"
pull_triggers = ["${data.docker_registry_image.emby.sha256_digest}"]
}
resource "docker_image" "mariadb" {
name = "${data.docker_registry_image.mariadb.name}"
pull_triggers = ["${data.docker_registry_image.mariadb.sha256_digest}"]
}
resource "docker_image" "transmission" {
name = "${data.docker_registry_image.transmission.name}"
pull_triggers = ["${data.docker_registry_image.transmission.sha256_digest}"]
}
resource "docker_image" "traefik16" {
name = "${data.docker_registry_image.traefik.name}"
pull_triggers = ["${data.docker_registry_image.traefik.sha256_digest}"]
}
resource "docker_image" "wikijs" {
name = "${data.docker_registry_image.wikijs.name}"
pull_triggers = ["${data.docker_registry_image.wikijs.sha256_digest}"]
}
resource "docker_image" "percona-mongodb-server" {
name = "${data.docker_registry_image.percona-mongodb-server.name}"
pull_triggers = ["${data.docker_registry_image.percona-mongodb-server.sha256_digest}"]
}
resource "docker_image" "ubooquity" {
name = data.docker_registry_image.ubooquity.name
pull_triggers = [data.docker_registry_image.ubooquity.sha256_digest]
name = "${data.docker_registry_image.ubooquity.name}"
pull_triggers = ["${data.docker_registry_image.ubooquity.sha256_digest}"]
}
# resource "docker_image" "lychee" {
# name = "${data.docker_registry_image.lychee.name}"
# pull_triggers = ["${data.docker_registry_image.lychee.sha256_digest}"]
# Helps debug traefik reverse proxy headers
# Highly recommended!
# resource "docker_image" "headerdebug" {
# name = "${data.docker_registry_image.headerdebug.name}"
# pull_triggers = ["${data.docker_registry_image.headerdebug.sha256_digest}"]
# }
resource "docker_image" "lychee" {
name = "${data.docker_registry_image.lychee.name}"
pull_triggers = ["${data.docker_registry_image.lychee.sha256_digest}"]
}

View File

@ -0,0 +1,24 @@
data "docker_registry_image" "kib" {
name = "flavio/kube-image-bouncer:latest"
}
resource "docker_image" "kib" {
name = "${data.docker_registry_image.kib.name}"
pull_triggers = ["${data.docker_registry_image.kib.sha256_digest}"]
}
resource "docker_container" "kib" {
name = "kib"
image = "${docker_image.kib.latest}"
labels = "${merge(
local.traefik_common_labels,
map(
"traefik.port", 1323,
"traefik.frontend.rule","Host:kib.b88.fun"
))}"
restart = "unless-stopped"
destroy_grace_seconds = 10
must_run = true
}

View File

@ -1,17 +1,18 @@
locals {
traefik_common_labels = {
traefik_common_labels {
"traefik.enable" = "true"
// HSTS
"traefik.frontend.headers.SSLTemporaryRedirect" = "true"
"traefik.frontend.headers.STSSeconds" = "2592000"
"traefik.frontend.headers.STSIncludeSubdomains" = "false"
// X-Powered-By, Server headers
"traefik.frontend.headers.customResponseHeaders" = var.xpoweredby
"traefik.frontend.headers.customResponseHeaders" = "${var.xpoweredby}"
// X-Frame-Options
"traefik.frontend.headers.customFrameOptionsValue" = var.xfo_allow
"traefik.frontend.headers.customFrameOptionsValue" = "${var.xfo_allow}"
"traefik.frontend.headers.contentTypeNosniff" = "true"
"traefik.frontend.headers.browserXSSFilter" = "true"
"traefik.docker.network" = "traefik"
}
}

View File

@ -1,30 +1,37 @@
# resource "docker_container" "lychee" {
# name = "lychee"
# image = "${docker_image.lychee.image_id}"
# restart = "unless-stopped"
# destroy_grace_seconds = 10
# must_run = true
# volumes {
# host_path = "/mnt/xwing/config/lychee"
# container_path = "/config"
# }
# volumes {
# host_path = "/mnt/xwing/data/lychee"
# container_path = "/pictures"
# }
# upload {
# content = "${file("${path.module}/conf/lychee.php.ini")}"
# file = "/config/lychee/user.ini"
# }
# labels = "${merge(
# local.traefik_common_labels,
# map(
# "traefik.port", 80,
# "traefik.frontend.rule", "Host:pics.${var.domain}",
# ))}"
# env = [
# "PUID=986",
# "PGID=984",
# ]
# # links = ["${var.links-mariadb}"]
# }
resource "docker_container" "lychee" {
name = "lychee"
image = "${docker_image.lychee.latest}"
restart = "unless-stopped"
destroy_grace_seconds = 10
must_run = true
volumes {
host_path = "/mnt/xwing/config/lychee"
container_path = "/config"
}
volumes {
host_path = "/mnt/xwing/data/lychee"
container_path = "/pictures"
}
upload {
content = "${file("${path.module}/conf/lychee.php.ini")}"
file = "/config/lychee/user.ini"
}
labels = "${merge(
local.traefik_common_labels,
map(
"traefik.port", 80,
"traefik.frontend.rule", "Host:pics.${var.domain}",
))}"
env = [
"PUID=986",
"PGID=984",
]
links = ["${docker_container.mariadb.name}"]
}

1
docker/main.tf Normal file
View File

@ -0,0 +1 @@

View File

@ -1,6 +0,0 @@
resource "docker_network" "traefik" {
name = "traefik"
driver = "bridge"
internal = true
}

View File

@ -1,16 +1,23 @@
# output "lychee-ip" {
# value = "${docker_container.lychee.ip_address}"
# }
output "names-traefik" {
value = docker_container.traefik.name
output "lychee-ip" {
value = "${docker_container.lychee.ip_address}"
}
output "traefik-network-id" {
value = docker_network.traefik.id
output "names-transmission" {
value = "${docker_container.transmission.name}"
}
output "names-emby" {
value = "${docker_container.emby.name}"
}
output "names-mariadb" {
value = "${docker_container.mariadb.name}"
}
output "names-traefik" {
value = "${docker_container.traefik.name}"
}
output "auth-header" {
value = var.basic_auth
value = "${var.basic_auth}"
}

View File

@ -1,19 +0,0 @@
terraform {
required_providers {
pass = {
source = "camptocamp/pass"
}
digitalocean = {
source = "digitalocean/digitalocean"
}
postgresql = {
source = "cyrilgdn/postgresql"
}
cloudflare = {
source = "cloudflare/cloudflare"
}
docker = {
source = "kreuzwerker/docker"
}
}
}

View File

@ -1,95 +1,80 @@
resource "docker_container" "traefik" {
name = "traefik"
image = docker_image.traefik17.image_id
image = "${docker_image.traefik16.latest}"
labels {
label = "traefik.enable"
value = "true"
# Admin Backend
ports {
internal = 1111
external = 1111
ip = "${var.ips["eth0"]}"
}
labels {
label = "traefik.http.routers.api.rule"
value = "Host('traefik.in.bb8.fun')"
}
labels {
label = "traefik.http.routers.api.service"
value = "api@internal"
ports {
internal = 1111
external = 1111
ip = "${var.ips["tun0"]}"
}
# Local Web Server
ports {
internal = 80
external = 80
ip = var.ips["eth0"]
ip = "${var.ips["eth0"]}"
}
# Local Web Server (HTTPS)
ports {
internal = 443
external = 443
ip = var.ips["eth0"]
ip = "${var.ips["eth0"]}"
}
# Proxied via sydney.captnemo.in
ports {
internal = 443
external = 443
ip = var.ips["tun0"]
ip = "${var.ips["tun0"]}"
}
ports {
internal = 80
external = 80
ip = var.ips["tun0"]
ip = "${var.ips["tun0"]}"
}
upload {
content = file("${path.module}/conf/traefik.toml")
content = "${file("${path.module}/conf/traefik.toml")}"
file = "/etc/traefik/traefik.toml"
}
upload {
content = file(
"/home/nemo/projects/personal/certs/git.captnemo.in/fullchain.pem",
)
file = "/etc/traefik/git.captnemo.in.crt"
content = "${file("/home/nemo/projects/personal/certs/git.captnemo.in/fullchain.pem")}"
file = "/etc/traefik/git.captnemo.in.crt"
}
upload {
content = file(
"/home/nemo/projects/personal/certs/git.captnemo.in/privkey.pem",
)
file = "/etc/traefik/git.captnemo.in.key"
content = "${file("/home/nemo/projects/personal/certs/git.captnemo.in/privkey.pem")}"
file = "/etc/traefik/git.captnemo.in.key"
}
upload {
content = file(
"/home/nemo/projects/personal/certs/lego/certificates/tatooine.club.key",
)
file = "/etc/traefik/tatooine.club.key"
content = "${file("/home/nemo/projects/personal/certs/rss.captnemo.in/fullchain.pem")}"
file = "/etc/traefik/rss.captnemo.in.crt"
}
upload {
content = file(
"/home/nemo/projects/personal/certs/lego/certificates/tatooine.club.crt",
)
file = "/etc/traefik/tatooine.club.crt"
content = "${file("/home/nemo/projects/personal/certs/rss.captnemo.in/privkey.pem")}"
file = "/etc/traefik/rss.captnemo.in.key"
}
upload {
content = file(
"/home/nemo/projects/personal/certs/rss.captnemo.in/fullchain.pem",
)
file = "/etc/traefik/rss.captnemo.in.crt"
content = "${file("/home/nemo/projects/personal/certs/emby.in.bb8.fun/privkey.pem")}"
file = "/etc/traefik/emby.in.bb8.fun.key"
}
upload {
content = file(
"/home/nemo/projects/personal/certs/rss.captnemo.in/privkey.pem",
)
file = "/etc/traefik/rss.captnemo.in.key"
content = "${file("/home/nemo/projects/personal/certs/emby.in.bb8.fun/fullchain.pem")}"
file = "/etc/traefik/emby.in.bb8.fun.crt"
}
volumes {
@ -104,20 +89,10 @@ resource "docker_container" "traefik" {
}
memory = 256
restart = "always"
restart = "unless-stopped"
destroy_grace_seconds = 10
must_run = true
// `bridge` is auto-connected for now
// https://github.com/terraform-providers/terraform-provider-docker/issues/10
networks_advanced {
name = "traefik"
}
networks_advanced {
name = "bridge"
}
env = [
"CLOUDFLARE_EMAIL=${var.cloudflare_email}",
"CLOUDFLARE_API_KEY=${var.cloudflare_key}",

49
docker/transmission.tf Normal file
View File

@ -0,0 +1,49 @@
resource "docker_container" "transmission" {
name = "transmission"
image = "${docker_image.transmission.latest}"
labels = "${merge(
local.traefik_common_labels,
map(
"traefik.frontend.auth.basic", "${var.basic_auth}",
"traefik.port", 9091,
))}"
ports {
internal = 51413
external = 51413
ip = "${var.ips["eth0"]}"
protocol = "udp"
}
volumes {
host_path = "/mnt/xwing/config/transmission"
container_path = "/config"
}
volumes {
host_path = "/mnt/xwing/media/DL"
container_path = "/downloads"
}
volumes {
host_path = "/mnt/xwing/data/watch/transmission"
container_path = "/watch"
}
upload {
content = "${file("${path.module}/conf/transmission.json")}"
file = "/config/settings.json"
}
env = [
"PGID=1003",
"PUID=1000",
"TZ=Asia/Kolkata",
]
memory = 1024
restart = "unless-stopped"
destroy_grace_seconds = 10
must_run = true
}

View File

@ -1,13 +1,6 @@
locals {
l = merge(local.traefik_common_labels, {
"traefik.port" = 3000
"traefik.frontend.rule" = "Host:${var.domain}"
})
}
resource "docker_container" "ubooquity" {
name = "ubooquity"
image = docker_image.ubooquity.image_id
image = "${docker_image.ubooquity.latest}"
restart = "unless-stopped"
destroy_grace_seconds = 30
@ -32,37 +25,31 @@ resource "docker_container" "ubooquity" {
host_path = "/mnt/xwing/media/EBooks/Comics"
container_path = "/comics"
}
labels {
label = "traefik.enable"
value = "true"
}
labels {
label = "traefik.admin.port"
value = 2203
}
labels {
label = "traefik.admin.frontend.rule"
value = "Host:library.${var.domain}"
}
labels {
label = "traefik.admin.frontend.auth.basic"
value = var.basic_auth
}
labels {
label = "traefik.read.port"
value = 2202
}
labels {
label = "traefik.read.frontend.rule"
value = "Host:read.${var.domain},comics.${var.domain},books.${var.domain}"
}
labels {
label = "traefik.docker.network"
value = "traefik"
"traefik.enable" = "true"
"traefik.admin.port" = 2203
"traefik.admin.frontend.rule" = "Host:library.${var.domain}"
# I do not trust the Ubooquity authentication
# it does some shady JS encryption
"traefik.admin.frontend.auth.basic" = "${var.basic_auth}"
"traefik.read.port" = 2202
"traefik.read.frontend.rule" = "Host:read.${var.domain},comics.${var.domain},books.${var.domain}"
"traefik.read.frontend.headers.SSLTemporaryRedirect" = "true"
"traefik.read.frontend.headers.STSSeconds" = "2592000"
"traefik.read.frontend.headers.STSIncludeSubdomains" = "false"
"traefik.read.frontend.headers.contentTypeNosniff" = "true"
"traefik.read.frontend.headers.browserXSSFilter" = "true"
"traefik.read.frontend.headers.customResponseHeaders" = "${var.xpoweredby}"
"traefik.frontend.headers.customFrameOptionsValue" = "${var.xfo_allow}"
}
upload {
content = file("${path.module}/conf/ubooquity.json")
content = "${file("${path.module}/conf/ubooquity.json")}"
file = "/config/preferences.json"
}
@ -73,4 +60,3 @@ resource "docker_container" "ubooquity" {
"MAXMEM=800",
]
}

View File

@ -1,18 +1,22 @@
variable "web_username" {
type = string
type = "string"
}
variable "web_password" {
type = string
type = "string"
}
variable "mysql_root_password" {
type = "string"
}
variable "cloudflare_key" {
type = string
type = "string"
description = "cloudflare API Key"
}
variable "cloudflare_email" {
type = string
type = "string"
description = "cloudflare email address"
}
@ -39,15 +43,18 @@ variable "refpolicy" {
}
variable "wiki_session_secret" {
type = string
type = "string"
}
variable "domain" {
type = string
type = "string"
}
variable "ips" {
type = map(string)
type = "map"
}
# variable "links-mariadb" {}
variable "mariadb-version" {
description = "mariadb version to use for fetching the docker image"
default = "10.3"
}

7
docker/volumes.tf Normal file
View File

@ -0,0 +1,7 @@
resource "docker_volume" "mariadb_volume" {
name = "mariadb_volume"
}
resource "docker_volume" "mongorocks_data_volume" {
name = "mongorocks_data_volume"
}

51
docker/wiki.tf Normal file
View File

@ -0,0 +1,51 @@
resource "docker_container" "wiki" {
name = "wiki"
image = "${docker_image.wikijs.latest}"
restart = "unless-stopped"
destroy_grace_seconds = 30
must_run = true
memory = 300
upload {
content = "${file("${path.module}/conf/wiki.yml")}"
file = "/var/wiki/config.yml"
}
volumes {
host_path = "/mnt/xwing/logs/wiki"
container_path = "/logs"
}
volumes {
host_path = "/mnt/xwing/data/wiki/repo"
container_path = "/repo"
}
volumes {
host_path = "/mnt/xwing/data/wiki/data"
container_path = "/data"
}
upload {
content = "${file("${path.module}/conf/humans.txt")}"
file = "/var/wiki/assets/humans.txt"
}
// The last header is a workaround for double header traefik bug
// This might be actually breaking iframe till the 1.5 Final release.
labels = "${merge(
local.traefik_common_labels,
map(
"traefik.frontend.rule", "Host:wiki.${var.domain}",
"traefik.frontend.passHostHeader", "true",
"traefik.port", 9999,
"traefik.frontend.headers.customResponseHeaders", "${var.xpoweredby}||Referrer-Policy:${var.refpolicy}||X-Frame-Options:${var.xfo_allow}",
))}"
links = ["${docker_container.mongorocks.name}"]
env = [
"WIKI_ADMIN_EMAIL=me@captnemo.in",
"SESSION_SECRET=${var.wiki_session_secret}",
]
}

View File

@ -1,12 +0,0 @@
module "echo-server" {
source = "./modules/container"
name = "echo-server"
image = "jmalloc/echo-server:latest"
web = {
expose = "true"
port = 8080
host = "debug.${var.root-domain},debug.in.${var.root-domain}"
}
}

View File

@ -1,45 +0,0 @@
module "elibsrv" {
name = "elibsrv"
source = "./modules/container"
image = "captn3m0/elibsrv"
resource = {
memory = 512
memory_swap = 512
}
web = {
expose = true
host = "ebooks.${var.root-domain}"
auth = true
}
volumes = [
{
host_path = "/mnt/xwing/media/EBooks"
container_path = "/books"
read_only = true
},
{
host_path = "/mnt/xwing/config/elibsrv"
container_path = "/config"
read_only = true
},
{
host_path = "/mnt/xwing/cache/elibsrv"
container_path = "/cache"
},
]
# The corresponding scan command is run using a cronjob
# `docker run --volume "/mnt/xwing/media/EBooks:/books:ro" --volume "/mnt/xwing/config/elibsrv:/config" --env "elibsrv_thumbheight=320" captn3m0/elibsrv scan
command = ["serve"]
keep_image = true
env = [
"elibsrv_thumbheight=320",
"elibsrv_title=Scarif Media Archives",
]
networks = ["bridge"]
}

View File

@ -2,26 +2,20 @@
; Copy required sections to your own app.ini (default is custom/conf/app.ini)
; and modify as needed.
; See the cheatsheet at https://docs.gitea.io/en-us/config-cheat-sheet/
; A sample file with all configuration documented is at https://github.com/go-gitea/gitea/blob/main/custom/conf/app.example.ini
; App name that shows on every page title
APP_NAME = Nemo's code
RUN_MODE = prod
RUN_USER = git
WORK_PATH=/data/gitea
[repository]
ROOT = /data/git/repositories
USE_COMPAT_SSH_URI = false
USE_COMPAT_SSH_URI = true
[repository.upload]
TEMP_PATH = /data/gitea/uploads
[ui]
;; Number of issues that are displayed on one page
ISSUE_PAGING_NUM = 20
; Value of `theme-color` meta tag, used by Android >= 5.0
; An invalid color like "none" or "disable" will have the default style
; More info: https://developers.google.com/web/updates/2014/11/Support-for-theme-color-in-Chrome-39-for-Android
@ -41,11 +35,6 @@ NOTICE_PAGING_NUM = 25
; Number of organization that are showed in one page
ORG_PAGING_NUM = 50
;; Whether to only show relevant repos on the explore page when no keyword is specified and default sorting is used.
;; A repo is considered irrelevant if it's a fork or if it has no metadata (no description, no icon, no topic).
ONLY_SHOW_RELEVANT_REPOS = true
[ui.user]
; Number of repos that are showed in one page
REPO_PAGING_NUM = 15
@ -63,9 +52,6 @@ ENABLE_HARD_LINE_BREAK = false
CUSTOM_URL_SCHEMES = git,magnet,steam,irc,slack
FILE_EXTENSIONS = .md,.markdown,.mdown,.mkd
;; Enables math inline and block detection
ENABLE_MATH = true
; Define allowed algorithms and their minimum key length (use -1 to disable a type)
[ssh.minimum_key_sizes]
ED25519 = 256
@ -73,17 +59,17 @@ ECDSA = 256
RSA = 2048
DSA = 1024
[lfs]
PATH=/data/gitea/lfs
[server]
APP_DATA_PATH = /data/gitea
SSH_DOMAIN = git.captnemo.in
HTTP_PORT = 3000
ROOT_URL = https://git.captnemo.in/
DISABLE_SSH = true
DISABLE_SSH = false
SSH_PORT = 22
DOMAIN = git.captnemo.in
LFS_START_SERVER = true
LFS_JWT_SECRET = "${lfs-jwt-secret}"
LFS_CONTENT_PATH = /data/gitea/lfs
LFS_JWT_SECRET = ${lfs-jwt-secret}
OFFLINE_MODE = true
LANDING_PAGE = explore
MINIMUM_KEY_SIZE_CHECK = true
@ -93,8 +79,6 @@ SSH_SERVER_CIPHERS = chacha20-poly1305@openssh.com, aes256-gcm@openssh.com, aes1
SSH_SERVER_KEY_EXCHANGES = curve25519-sha256@libssh.org, ecdh-sha2-nistp521, ecdh-sha2-nistp384, ecdh-sha2-nistp256, diffie-hellman-group-exchange-sha256
SSH_SERVER_MACS = hmac-sha2-512-etm@openssh.com, hmac-sha2-256-etm@openssh.com, umac-128-etm@openssh.com, hmac-sha2-512, hmac-sha2-256, umac-128@openssh.com
DISABLE_ROUTER_LOG = true
ENABLE_GZIP = true
[database]
; TODO
@ -103,7 +87,7 @@ DB_TYPE = sqlite3
HOST = mariadb:3306
NAME = gitea
USER = gitea
; PASSWD = "mysql-password"
; PASSWD = "${mysql-password}"
; ; For "postgres" only, either "disable", "require" or "verify-full"
; SSL_MODE = disable
; ; For "sqlite3" and "tidb", use absolute path when you start as service
@ -112,9 +96,10 @@ PATH = /data/gitea/gitea.db
SQLITE_TIMEOUT = 500
; ; For iterate buffer, default is 50
; ITERATE_BUFFER_SIZE = 50
; Show the database generated SQL
LOG_SQL = false
SQLITE_JOURNAL_MODE = WAL
[session]
PROVIDER_CONFIG = /data/gitea/sessions
PROVIDER = file
[picture]
AVATAR_UPLOAD_PATH = /data/gitea/avatars
@ -126,11 +111,9 @@ ISSUE_INDEXER_PATH = indexers/issues.bleve
; repo indexer by default disabled, since it uses a lot of disk space
REPO_INDEXER_ENABLED = true
REPO_INDEXER_PATH = indexers/repos.bleve
UPDATE_BUFFER_LEN = 20
MAX_FILE_SIZE = 1048576
[queue.issue_indexer]
LENGTH = 100
[admin]
; Disable regular (non-admin) users to create organizations
DISABLE_REGULAR_ORG_CREATION = false
@ -139,10 +122,10 @@ DISABLE_REGULAR_ORG_CREATION = false
INSTALL_LOCK = true
LOGIN_REMEMBER_DAYS = 30
MIN_PASSWORD_LENGTH = 10
IMPORT_LOCAL_PATHS = true
IMPORT_LOCAL_PATHS = false
DISABLE_GIT_HOOKS = true
SECRET_KEY = "${secret_key}"
INTERNAL_TOKEN = "${internal_token}"
SECRET_KEY = ${secret_key}
INTERNAL_TOKEN = ${internal_token}
[service]
; ; More detail: https://github.com/gogits/gogs/issues/165
@ -155,16 +138,14 @@ ACTIVE_CODE_LIVE_MINUTES = 15
RESET_PASSWD_CODE_LIVE_MINUTES = 30
REGISTER_EMAIL_CONFIRM = true
ENABLE_NOTIFY_MAIL = true
DISABLE_REGISTRATION = true
DISABLE_REGISTRATION = false
; ; Enable captcha validation for registration
ENABLE_CAPTCHA = true
REQUIRE_EXTERNAL_REGISTRATION_CAPTCHA = true
CAPTCHA_TYPE = image
; ; User must sign in to view anything.
REQUIRE_SIGNIN_VIEW = false
; ; Default value for KeepEmailPrivate
; ; New user will get the value of this setting copied into their profile
DEFAULT_KEEP_EMAIL_PRIVATE = true
DEFAULT_KEEP_EMAIL_PRIVATE = false
; ; Default value for AllowCreateOrganization
; ; New user will have rights set to create organizations depending on this setting
DEFAULT_ALLOW_CREATE_ORGANIZATION = true
@ -182,54 +163,43 @@ ENABLED = true
FROM = git@captnemo.in
USER = git@captnemo.in
PASSWD = ${smtp_password}
PROTOCOL = smtps
SMTP_ADDR = smtp.migadu.com
SMTP_PORT = 465
HOST = smtp.migadu.com:587
SEND_AS_PLAIN_TEXT = true
SUBJECT_PREFIX = "[git.captnemo.in] "
[cache]
ADAPTER = redis
INTERVAL = 60
HOST = "network=tcp,addr=gitea-redis:6379,db=0,pool_size=100,idle_timeout=180"
ITEM_TTL = 16h
[session]
; ; Either "memory", "file", or "redis", default is "memory"
PROVIDER = redis
; Provider config options
; redis: network=tcp,addr=:6379,password=macaron,db=0,pool_size=100,idle_timeout=180
PROVIDER_CONFIG = "network=tcp,addr=gitea-redis:6379,db=1,pool_size=100,idle_timeout=180"
; ; Session cookie name
COOKIE_NAME = i_like_gitea
; ; If you use session in https only, default is false
COOKIE_SECURE = true
; SameSite settings. Either "none", "lax", or "strict"
SAME_SITE = strict
[migrations]
ALLOWED_DOMAINS = github.com
ALLOW_LOCALNETWORKS = false
; ; Enable set cookie, default is true
ENABLE_SET_COOKIE = true
; ; Session GC time interval in seconds, default is 86400 (1 day)
; GC_INTERVAL_TIME = 86400
; ; Session life time in seconds, default is 86400 (1 day)
SESSION_LIFE_TIME = 2592000
[attachment]
; ; Whether attachments are enabled. Defaults to `true`
ENABLE = true
; ; Path for attachments. Defaults to `data/attachments`
PATH = data/attachments
; ; One or more allowed types, e.g. image/jpeg|image/png
ALLOWED_TYPES = image/jpeg|image/png|application/zip|application/gzip|application/pdf|text/csv
; ; Max size of each file. Defaults to 32MB
MAX_SIZE = 200
; MAX_SIZE = 4
; ; Max number of files per upload. Defaults to 10
MAX_FILES = 10
; MAX_FILES = 5
[log]
; Either "console", "file", "conn", "smtp" or "database", default is "console"
; Use comma to separate multiple modes, e.g. "console, file"
MODE = console
; Buffer length of the channel, keep it as it is if you don't know what it is.
BUFFER_LEN = 10000
; Either "Trace", "Debug", "Info", "Warn", "Error", "Critical", default is "Trace"
LEVEL = Warn
REDIRECT_MACARON_LOG = true
ROUTER_LOG_LEVEL = Critical
logger.access.MODE=,
logger.xorm.MODE=,
LEVEL = Info
[cron]
; Enable running cron tasks periodically.
@ -237,30 +207,10 @@ ENABLED = true
; ; Run cron tasks when Gitea starts.
RUN_AT_START = false
[cron.archive_cleanup]
RUN_AT_START = true
SCHEDULE = @midnight
; Archives created more than OLDER_THAN ago are subject to deletion
OLDER_THAN = 24h
; ; Update mirrors
[cron.update_mirrors]
SCHEDULE = @every 3h
; Repository health check
[cron.repo_health_check]
SCHEDULE = @midnight
TIMEOUT = 60s
; Arguments for command 'git fsck', e.g. "--unreachable --tags"
; see more on http://git-scm.com/docs/git-fsck
ARGS =
; Check repository statistics
[cron.check_repo_stats]
RUN_AT_START = true
SCHEDULE = @midnight
[api]
; Max number of items will response in a page
MAX_RESPONSE_ITEMS = 100
@ -274,40 +224,4 @@ SHOW_FOOTER_TEMPLATE_LOAD_TIME = false
[openid]
ENABLE_OPENID_SIGNIN = true
ENABLE_OPENID_SIGNUP = false
[metrics]
; Enables metrics endpoint. True or false; default is false.
ENABLED = true
[oauth2]
ENABLE = false
; this is same as JWT secret above
JWT_SECRET = "${oauth2-jwt-secret}"
[federation]
ENABLED=false
;; Enable/Disable user statistics for nodeinfo if federation is enabled
;SHARE_USER_STATISTICS = true
;;
;; Maximum federation request and response size (MB)
;MAX_SIZE = 4
;;
;; WARNING: Changing the settings below can break federation.
;;
;; HTTP signature algorithms
;ALGORITHMS = rsa-sha256, rsa-sha512, ed25519
;;
;; HTTP signature digest algorithm
;DIGEST_ALGORITHM = SHA-256
;;
;; GET headers for federation requests
;GET_HEADERS = (request-target), Date
;;
;; POST headers for federation requests
;POST_HEADERS = (request-target), Date, Digest
[packages]
;; Enable/Disable package registry capabilities
ENABLED = true
ENABLE_OPENID_SIGNUP = true

View File

@ -1,56 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
version="1.0"
width="2000.000000pt"
height="2000.000000pt"
viewBox="0 0 2000.000000 2000.000000"
preserveAspectRatio="xMidYMid meet"
id="svg10"
sodipodi:docname="favicon.svg"
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs14" />
<sodipodi:namedview
id="namedview12"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="pt"
showgrid="false"
inkscape:zoom="0.23281491"
inkscape:cx="1232.7389"
inkscape:cy="1415.2874"
inkscape:window-width="1920"
inkscape:window-height="1037"
inkscape:window-x="0"
inkscape:window-y="18"
inkscape:window-maximized="1"
inkscape:current-layer="g8" />
<metadata
id="metadata2">
Created by potrace 1.16, written by Peter Selinger 2001-2019
</metadata>
<g
transform="translate(0.000000,2000.000000) scale(0.100000,-0.100000)"
fill="#000000"
stroke="none"
id="g8"
style="fill:#000080">
<path
d="M0 10000 l0 -10000 10000 0 10000 0 0 10000 0 10000 -10000 0 -10000 0 0 -10000z m11852 5356 c553 -141 882 -698 738 -1251 -27 -102 -104 -261 -168 -346 -71 -94 -197 -207 -296 -265 -109 -65 -274 -121 -405 -136 l-100 -12 -90 -221 c-69 -169 -87 -222 -76 -227 12 -7 1420 -613 2145 -923 162 -69 310 -132 328 -140 31 -14 32 -16 20 -44 -7 -15 -55 -127 -107 -247 -52 -121 -96 -221 -98 -223 -4 -5 -131 48 -1385 585 -608 261 -1111 474 -1116 474 -5 0 -19 -24 -31 -52 -76 -181 -1440 -3576 -1474 -3667 -16 -43 -21 -81 -21 -166 -1 -99 2 -116 26 -167 38 -81 83 -133 158 -182 160 -104 244 -120 614 -113 383 7 564 38 731 125 90 47 218 173 263 258 67 128 79 306 32 471 -11 40 -20 75 -20 78 0 3 91 5 203 5 402 0 680 43 1017 156 226 76 540 218 768 348 35 20 66 36 68 36 9 0 3 -122 -11 -237 -57 -462 -214 -845 -470 -1152 -100 -119 -281 -291 -403 -383 -92 -70 -344 -228 -363 -228 -4 0 -35 29 -70 65 -105 109 -219 151 -345 125 -36 -7 -108 -38 -184 -78 -489 -261 -847 -376 -1345 -434 -180 -21 -653 -15 -955 11 -140 13 -338 25 -440 28 l-185 5 125 -126 125 -126 75 6 c97 8 170 -17 234 -82 65 -64 90 -137 82 -234 l-6 -75 206 -206 206 -207 83 6 c73 4 89 2 137 -20 184 -84 232 -302 100 -449 -67 -75 -110 -94 -212 -94 -68 0 -93 5 -125 22 -51 27 -119 100 -140 150 -19 43 -24 127 -12 188 l8 40 -201 200 -200 200 0 -531 0 -531 26 -14 c41 -22 101 -96 118 -146 38 -110 8 -222 -80 -302 -96 -88 -207 -103 -321 -45 -134 69 -192 232 -130 367 26 58 83 119 128 139 l29 13 0 531 0 532 -28 11 c-42 18 -108 89 -132 144 -24 53 -28 144 -10 191 11 30 9 32 -203 245 -117 119 -219 230 -226 246 -44 103 -170 239 -486 523 -412 371 -643 616 -819 865 -236 336 -397 688 -501 1092 -44 170 -80 249 -141 305 -76 70 -138 92 -263 95 l-106 2 -28 109 c-49 190 -70 366 -71 589 -1 220 10 324 54 505 61 246 161 471 308 691 134 200 315 410 326 378 3 -8 19 -68 36 -134 136 -520 354 -976 638 -1332 95 -119 277 -319 322 -354 l33 -25 -89 -49 c-166 -93 -288 -240 -324 -393 -15 -66 -15 -212 0 -289 24 -120 126 -300 267 -476 139 -172 374 -408 455 -456 181 -106 352 -125 492 -54 66 33 153 123 193 198 17 33 365 794 773 1690 408 897 760 1668 782 1715 72 154 120 262 116 265 -1 1 -91 40 -198 85 -321 136 -871 371 -935 400 -33 15 -161 70 -285 123 -735 312 -1076 459 -1082 466 -11 10 201 501 216 501 6 0 200 -81 431 -181 1489 -641 2052 -882 2070 -886 17 -3 33 24 118 212 l97 217 -48 61 c-96 122 -154 239 -194 392 -30 114 -36 323 -13 436 23 114 72 242 131 341 58 96 199 245 293 308 124 83 285 146 437 170 97 15 276 4 386 -24z"
id="path4"
style="fill:#192a56;fill-opacity:1" />
<path
d="M11496 14790 c-110 -28 -228 -126 -281 -234 -103 -210 -11 -470 203 -577 65 -33 71 -34 187 -34 116 0 122 1 187 34 82 41 169 128 204 206 99 217 11 466 -202 571 -66 33 -83 37 -166 40 -51 2 -110 -1 -132 -6z"
id="path6"
style="fill:#192a56;fill-opacity:1" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 4.1 KiB

View File

@ -1,22 +0,0 @@
User-agent: MJ12bot
Disallow: /
User-agent: SemrushBot
Disallow: /
User-agent: SemrushBot-SA
Disallow: /
User-agent: rogerbot
Disallow:/
User-agent: dotbot
Disallow:/
User-agent: AhrefsBot
Disallow: /
User-agent: Alexibot
Disallow: /
User-agent: SurveyBot
Disallow: /
User-agent: Xenus
Disallow: /
User-agent: Xenus Link Sleuth 1.1c
Disallow: /
User-agent: AhrefsBot
Disallow: /

View File

@ -1,22 +0,0 @@
User-agent: MJ12bot
Disallow: /
User-agent: SemrushBot
Disallow: /
User-agent: SemrushBot-SA
Disallow: /
User-agent: rogerbot
Disallow:/
User-agent: dotbot
Disallow:/
User-agent: AhrefsBot
Disallow: /
User-agent: Alexibot
Disallow: /
User-agent: SurveyBot
Disallow: /
User-agent: Xenus
Disallow: /
User-agent: Xenus Link Sleuth 1.1c
Disallow: /
User-agent: AhrefsBot
Disallow: /

View File

@ -1,6 +1,6 @@
# https://github.com/go-gitea/gitea/releases
data "docker_registry_image" "gitea" {
name = "gitea/gitea:1.21"
name = "gitea/gitea:1.4.1"
}
data "docker_registry_image" "redis" {
@ -8,14 +8,13 @@ data "docker_registry_image" "redis" {
}
data "template_file" "gitea-config-file" {
template = file("${path.module}/conf/conf.ini.tpl")
template = "${file("${path.module}/conf/conf.ini.tpl")}"
vars = {
secret_key = var.secret-key
internal_token = var.internal-token
smtp_password = var.smtp-password
lfs-jwt-secret = var.lfs-jwt-secret
mysql-password = var.mysql-password
oauth2-jwt-secret = var.oauth2-jwt-secret
vars {
secret_key = "${var.secret-key}"
internal_token = "${var.internal-token}"
smtp_password = "${var.smtp-password}"
lfs-jwt-secret = "${var.lfs-jwt-secret}"
mysql-password = "${var.mysql-password}"
}
}

View File

@ -1,89 +1,71 @@
locals {
l = merge(var.traefik-labels, {
"traefik.port" = 3000
"traefik.frontend.rule" = "Host:${var.domain}"
})
}
resource "docker_container" "gitea" {
name = "gitea"
image = docker_image.gitea.image_id
image = "${docker_image.gitea.latest}"
dynamic "labels" {
for_each = local.l
content {
label = labels.key
value = labels.value
}
labels = "${merge(
var.traefik-labels, map(
"traefik.port", 3000,
"traefik.frontend.rule","Host:${var.domain}"
))}"
ports {
internal = 22
external = 2222
ip = "${var.ips["eth0"]}"
}
ports {
internal = 22
external = 2222
ip = "${var.ips["tun0"]}"
}
volumes {
volume_name = docker_volume.gitea_volume.name
volume_name = "${docker_volume.gitea_volume.name}"
container_path = "/data"
host_path = docker_volume.gitea_volume.mountpoint
host_path = "${docker_volume.gitea_volume.mountpoint}"
}
# For the following uploads, note that
# /data/gitea is GITEA_CUSTOM_PATH
# Logos
# TODO: Add svg
# https://docs.gitea.com/next/administration/customizing-gitea#changing-the-logo
# PNG images
upload {
content_base64 = filebase64("${path.module}/conf/public/img/gitea-lg.png")
file = "/data/gitea/public/img/logo.png"
content = "${file("${path.module}/conf/public/img/gitea-lg.png")}"
file = "/data/gitea/public/img/gitea-lg.png"
}
upload {
content_base64 = filebase64("${path.module}/conf/public/img/gitea-lg.png")
file = "/data/gitea/public/img/apple-touch-icon.png"
content = "${file("${path.module}/conf/public/img/gitea-sm.png")}"
file = "/data/gitea/public/img/gitea-sm.png"
}
upload {
content_base64 = filebase64("${path.module}/conf/public/img/gitea-sm.png")
file = "/data/gitea/public/img/favicon.png"
}
# SVG images
upload {
content_base64 = filebase64("${path.module}/conf/public/img/favicon.svg")
file = "/data/gitea/public/img/logo.svg"
content = "${file("${path.module}/conf/public/img/gitea-sm.png")}"
file = "/data/gitea/public/img/favicon.png"
}
upload {
content_base64 = filebase64("${path.module}/conf/public/img/favicon.svg")
file = "/data/gitea/public/img/favicon.svg"
content = "${file("${path.module}/../docker/conf/humans.txt")}"
file = "/data/gitea/public/humans.txt"
}
# Some files at top-level
upload {
content = file("${path.module}/../docker/conf/humans.txt")
file = "/data/gitea/humans.txt"
}
upload {
content = file("${path.module}/conf/public/robots.txt")
file = "/data/gitea/robots.txt"
}
# Extra Links in header
upload {
content = file("${path.module}/conf/extra_links.tmpl")
content = "${file("${path.module}/conf/extra_links.tmpl")}"
file = "/data/gitea/templates/custom/extra_links.tmpl"
}
# This is the main configuration file
upload {
content = data.template_file.gitea-config-file.rendered
content = "${data.template_file.gitea-config-file.rendered}"
file = "/data/gitea/conf/app.ini"
}
memory = 800
restart = "always"
memory = 256
restart = "unless-stopped"
destroy_grace_seconds = 10
must_run = true
networks = ["gitea", "traefik"]
links = [
"gitea-redis",
"mariadb",
]
}
resource "docker_image" "gitea" {
name = data.docker_registry_image.gitea.name
pull_triggers = [data.docker_registry_image.gitea.sha256_digest]
name = "${data.docker_registry_image.gitea.name}"
pull_triggers = ["${data.docker_registry_image.gitea.sha256_digest}"]
}

16
gitea/mysql.tf Normal file
View File

@ -0,0 +1,16 @@
resource "mysql_database" "gitea" {
name = "gitea"
}
resource "mysql_user" "gitea" {
user = "gitea"
host = "%"
plaintext_password = "${var.mysql-password}"
}
resource "mysql_grant" "gitea" {
user = "${mysql_user.gitea.user}"
host = "${mysql_user.gitea.host}"
database = "${mysql_database.gitea.name}"
privileges = ["ALL"]
}

View File

@ -1,5 +0,0 @@
resource "docker_network" "gitea" {
name = "gitea"
driver = "bridge"
}

View File

@ -1,19 +0,0 @@
terraform {
required_providers {
pass = {
source = "camptocamp/pass"
}
digitalocean = {
source = "digitalocean/digitalocean"
}
postgresql = {
source = "cyrilgdn/postgresql"
}
cloudflare = {
source = "cloudflare/cloudflare"
}
docker = {
source = "kreuzwerker/docker"
}
}
}

View File

@ -1,6 +1,6 @@
resource "docker_container" "redis" {
name = "gitea-redis"
image = docker_image.redis.image_id
image = "${docker_image.redis.latest}"
volumes {
host_path = "/mnt/xwing/cache/gitea"
@ -8,16 +8,12 @@ resource "docker_container" "redis" {
}
memory = 64
restart = "always"
restart = "unless-stopped"
destroy_grace_seconds = 10
must_run = true
networks = [docker_network.gitea.id]
}
resource "docker_image" "redis" {
name = data.docker_registry_image.redis.name
pull_triggers = [data.docker_registry_image.redis.sha256_digest]
keep_locally = true
name = "${data.docker_registry_image.redis.name}"
pull_triggers = ["${data.docker_registry_image.redis.sha256_digest}"]
}

View File

@ -1,32 +1,15 @@
variable "traefik-labels" {
type = map(string)
type = "map"
}
variable "domain" {
}
variable "domain" {}
variable "ips" {
type = map(string)
}
variable "secret-key" {
}
variable "internal-token" {
}
variable "smtp-password" {
}
variable "lfs-jwt-secret" {
}
variable "oauth2-jwt-secret" {
}
variable "mysql-password" {
}
variable "traefik-network-id" {
type = "map"
}
variable "secret-key" {}
variable "internal-token" {}
variable "smtp-password" {}
variable "lfs-jwt-secret" {}
variable "mysql-password" {}

View File

@ -1,4 +1,3 @@
resource "docker_volume" "gitea_volume" {
name = "gitea_volume"
}

34
heimdall/main.tf Normal file
View File

@ -0,0 +1,34 @@
data "docker_registry_image" "heimdall" {
name = "linuxserver/heimdall:latest"
}
resource "docker_image" "heimdall" {
name = "${data.docker_registry_image.heimdall.name}"
pull_triggers = ["${data.docker_registry_image.heimdall.sha256_digest}"]
}
resource "docker_container" "heimdall" {
name = "heimdall"
image = "${docker_image.heimdall.latest}"
labels = "${merge(
var.traefik-labels, map(
"traefik.port", "443",
"traefik.protocol", "https",
"traefik.frontend.rule","Host:${var.domain}",
"traefik.frontend.auth.basic", "${var.auth-header}",
))}"
volumes {
host_path = "/mnt/xwing/config/heimdall"
container_path = "/config"
}
env = [
"TZ=Asia/Kolkata",
]
restart = "unless-stopped"
destroy_grace_seconds = 10
must_run = true
}

11
heimdall/variables.tf Normal file
View File

@ -0,0 +1,11 @@
variable "domain" {
type = "string"
}
variable "auth-header" {
type = "string"
}
variable "traefik-labels" {
type = "map"
}

View File

@ -1,24 +0,0 @@
module "home-assistant" {
name = "home-assistant"
source = "../modules/container"
image = "ghcr.io/home-assistant/home-assistant:stable"
resource = {
memory = 1024
memory_swap = 1024
}
env = [
"TZ=Asia/Kolkata",
]
network_mode = "host"
volumes = [
{
container_path = "/config"
host_path = "/mnt/zwing/config/home-assistant"
},
]
}

View File

@ -1,16 +0,0 @@
module "jupyter" {
name = "jupyter"
source = "./modules/container"
image = "jupyter/scipy-notebook"
resource = {
memory = 1024
memory_swap = 4096
}
web = {
expose = "true"
host = "j.${var.root-domain}"
port = 8888
}
networks = ["bridge"]
gpu = true
}

View File

@ -1,21 +0,0 @@
# kaarana related stuff
# module "kaarana" {
# source = "./kaarana"
# root_db_password = data.pass_password.kaarana-root-db-password.password
# db_password = data.pass_password.kaarana-db-password.password
# providers = {
# docker = docker.sydney
# }
# }
data "pass_password" "kaarana-root-db-password" {
path = "KAARANA_DB_ROOT_PASSWORD"
}
data "pass_password" "kaarana-db-password" {
path = "KAARANA_DB_PASSWORD"
}

View File

@ -1,40 +0,0 @@
// Create a small database network
resource "docker_network" "kaarana-db" {
name = "kaarana-db"
labels = {
internal = "true"
role = "database"
}
internal = true
ipam_config {
subnet = "172.20.0.0/29"
gateway = "172.20.0.1"
}
}
// Run a small mySQL container in this subnet
resource "docker_container" "mysql" {
image = docker_image.db.image_id
name = "kaarana-mariadb"
restart = "always"
must_run = true
env = [
"MYSQL_ROOT_PASSWORD=${var.root_db_password}",
"MYSQL_USER=${local.username}",
"MYSQL_PASSWORD=${var.db_password}",
"MYSQL_DATABASE=${local.database}",
]
volumes {
host_path = "/mnt/disk/kaarana-db"
container_path = "/var/lib/mysql"
}
networks = ["kaarana-db"]
}

View File

@ -1,27 +0,0 @@
data "docker_registry_image" "wp" {
name = "wordpress:latest"
}
resource "docker_image" "wp" {
name = "wordpress"
pull_triggers = [data.docker_registry_image.wp.sha256_digest]
}
data "docker_registry_image" "db" {
name = "mariadb:10.4"
}
resource "docker_image" "db" {
name = "mariadb"
pull_triggers = [data.docker_registry_image.db.sha256_digest]
}
data "docker_registry_image" "traefik" {
name = "traefik:v2.0"
}
resource "docker_image" "traefik" {
name = "traefik"
pull_triggers = [data.docker_registry_image.db.sha256_digest]
}

View File

@ -1,64 +0,0 @@
// Create a small database network
resource "docker_network" "traefik" {
name = "traefik"
labels = {
internal = "true"
role = "ingress"
}
internal = true
}
resource "docker_container" "traefik" {
name = "traefik"
image = docker_image.traefik.image_id
# Do not offer HTTP2
# https://community.containo.us/t/traefikv2-http-2-0/1199
env = [
"GODEBUG=http2client=0",
]
upload {
content = file("${path.module}/traefik.toml")
file = "/etc/traefik/traefik.toml"
}
volumes {
host_path = "/var/run/docker.sock"
container_path = "/var/run/docker.sock"
read_only = true
}
volumes {
host_path = "/mnt/disk/traefik"
container_path = "/acme"
}
ports {
internal = 443
external = 8443
ip = "139.59.22.234"
}
ports {
internal = 80
external = 80
ip = "139.59.22.234"
}
memory = 256
restart = "always"
destroy_grace_seconds = 10
must_run = true
networks_advanced {
name = "bridge"
}
networks_advanced {
name = "traefik"
}
}

View File

@ -1,45 +0,0 @@
# This configures docker service discovery
[providers.docker]
exposedByDefault = false
network = "traefik"
defaultRule = ""
[entryPoints]
[entryPoints.web]
address = ":80"
[entryPoints.web-secure]
address = ":443"
[http.middlewares]
[http.middlewares.everything.redirectScheme]
scheme = "https"
[tcp.routers]
[tcp.routers.forwardtohome]
entryPoints = ["web-secure"]
rule = "HostSNI(`emby.bb8.fun`, `git.captnemo.in`)"
service = "homeserver"
[tcp.routers.forwardtohome.tls]
passthrough = true
[tcp.services]
[tcp.services.homeserver.loadBalancer]
[[tcp.services.homeserver.loadBalancer.servers]]
address = "10.8.0.14:443"
[certificatesResolvers.default.acme]
email = "certs@captnemo.in"
storage = "/acme/acme.json"
[certificatesResolvers.default.acme.httpChallenge]
# used during the challenge
entryPoint = "web"
[tls.options]
[tls.options.foo]
minVersion = "VersionTLS12"
cipherSuites = [
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
"TLS_RSA_WITH_AES_256_GCM_SHA384"
]

View File

@ -1,12 +0,0 @@
variable "root_db_password" {
}
variable "db_password" {
}
locals {
username = "wordpress"
database = "wordpress"
db_hostname = "kaarana.db"
}

View File

@ -1,40 +0,0 @@
resource "docker_container" "wp" {
image = docker_image.wp.image_id
name = "kaarana-wordpress"
restart = "always"
must_run = true
labels = {
"traefik.enable" = "true"
"traefik.tcp.routers.kaarana.rule" = "HostSNI(`kaarana.captnemo.in`)"
"traefik.tcp.routers.kaarana.tls" = "true"
# "traefik.tcp.routers.kaarana.tls.options" = "foo"
"traefik.tcp.services.wordpress.loadbalancer.server.port" = "80"
# "traefik.tcp.routers.kaarana.entrypoints" = "web-secure"
"traefik.tcp.routers.kaarana.tls.certResolver" = "default"
"traefik.tcp.routers.kaarana.tls.domains[0].main" = "kaarana.captnemo.in"
}
env = [
"WORDPRESS_DB_HOST=${local.db_hostname}",
"WORDPRESS_DB_USER=${local.username}",
"WORDPRESS_DB_PASSWORD=${var.db_password}",
"WORDPRESS_DB_NAME=${local.database}",
"WORDPRESS_TABLE_PREFIX=",
]
volumes {
host_path = "/mnt/disk/kaarana-wp"
container_path = "/var/www/html"
}
ports {
internal = 80
external = 8213
ip = "10.8.0.1"
}
networks = ["bridge", "kaarana-db"]
}

View File

@ -1,33 +0,0 @@
# module "kavita" {
# name = "kavita"
# source = "./modules/container"
# image = "kizaing/kavita:latest"
# web = {
# expose = true
# port = 5000
# host = "kavita.bb8.fun"
# }
# resource = {
# memory = 1024
# memory_swap = 1024
# }
# volumes = [
# {
# host_path = "/mnt/xwing/media/EBooks"
# container_path = "/ebooks"
# },
# {
# host_path = "/mnt/xwing/config/kavita"
# container_path = "/kavita/config"
# }
# ]
# networks = ["traefik"]
# env = [
# "TZ=Asia/Kolkata",
# ]
# }

View File

@ -1,41 +0,0 @@
# // Points to the local working directory instead of
# // the published version
# module "kayak" {
# source = "../terraform-digitalocean-kayak"
# cert_path = "${path.root}/secrets/kayak"
# domain = "kayak.${var.root-domain}"
# ssh_key = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQD0Getey8585AqdgIl9mqQ3SH9w6z7NZUW4HXdOqZwC7sYEaDrLOBV014gtFS8h8ymm4dcw6xEGUkaavcHC8W9ChTLKBMK4N1/sUS/umLy+Wi/K//g13y0VHSdvcc+gMQ27b9n/DwDY4ZKkaf6t+4HWyFWNh6gp0cT1WCyLNlsER55KUdy+C1lCOpv1SMepOaYc7uyBlC9FfgewJho/OfxnoTztQV6QeSGfr2Xr94Ip1FUPoLoBLLilh4ZbCe6F6bqn0kNgVBTkrVwWJv5Z0jCJpUjER69cqjASRao9KCHkyPtybzKKhCLZIlB3QMggEv0xnlHMpeeuDWcGrBVPKI8V"
# asset_dir = "${path.root}/k8s"
# providers {
# docker = "docker.kayak"
# }
# }
# provider "docker" {
# host = "tcp://${cloudflare_record.kayak-docker.hostname}:2376"
# version = "~> 2.0.0"
# alias = "kayak"
# ca_material = "${module.kayak.docker_ca_cert}"
# cert_material = "${module.kayak.docker_client_cert}"
# key_material = "${module.kayak.docker_client_key}"
# }
# resource "cloudflare_record" "kayak-docker" {
# name = "docker.kayak"
# value = "${module.kayak.droplet_ipv4}"
# domain = "${var.root-domain}"
# type = "A"
# ttl = 120
# }
# resource "cloudflare_record" "kayak" {
# name = "kayak"
# value = "${module.kayak.droplet_ipv4}"
# domain = "${var.root-domain}"
# type = "A"
# ttl = 120
# }
# resource "cloudflare_record" "kayak-etcd" {
# name = "etcd.kayak"
# value = "${module.kayak.droplet_ipv4_private}"
# domain = "${var.root-domain}"
# type = "A"
# ttl = 120
# }

View File

@ -1,40 +0,0 @@
module "klaxon-db" {
source = "./modules/postgres"
name = "klaxon"
password = data.pass_password.klaxon-db-password.password
}
module "klaxon" {
name = "klaxon"
source = "./modules/container"
web = {
expose = true
port = "3000"
host = "klaxon.${var.root-domain}"
}
resource = {
memory = 1024
memory_swap = 1024
}
env = [
"DATABASE_URL=postgres://klaxon:${data.pass_password.klaxon-db-password.password}@postgres/klaxon",
"ADMIN_EMAILS=klaxon.admin@captnemo.in",
"RAILS_ENV=production",
"SECRET_KEY_BASE=${data.pass_password.klaxon-secret-key.password}",
"SENDGRID_USERNAME=apikey",
"SENDGRID_PASSWORD=${data.pass_password.klaxon-sendgrid-password.password}",
"KLAXON_FORCE_SSL=false",
"KLAXON_COMPILE_ASSETS=true",
"ADMIN_EMAILS=klaxon@captnemo.in",
"MAILER_FROM_ADDRESS=klaxon@sendgrid.captnemo.in",
]
restart = "always"
image = "themarshallproject/klaxon"
networks = ["postgres", "external"]
}

View File

@ -1,19 +0,0 @@
// Bring up a simple test container
// In the controller node
# resource "kubernetes_pod" "nginx" {
# metadata {
# name = "terraform-example"
# namespace = "default"
# }
# spec {
# toleration {
# key = "node-role.kubernetes.io/master"
# operator = "Exists"
# effect = "NoSchedule"
# }
# container {
# image = "nginx:latest"
# name = "nginx"
# }
# }
# }

162
main.tf
View File

@ -1,112 +1,112 @@
module "cloudflare" {
source = "./cloudflare"
domain = "bb8.fun"
zone_id = lookup(data.cloudflare_zones.bb8.zones[0], "id")
ips = var.ips
source = "cloudflare"
domain = "bb8.fun"
ips = "${var.ips}"
}
droplet_ip = module.digitalocean.droplet_ipv4
module "mysql" {
source = "mysql"
mysql_root_password = "${var.mysql_root_password}"
mysql_lychee_password = "${var.mysql_lychee_password}"
mysql_airsonic_password = "${var.mysql_airsonic_password}"
mysql_kodi_password = "${var.mysql_kodi_password}"
lychee_ip = "${module.docker.lychee-ip}"
}
module "docker" {
source = "./docker"
web_username = data.pass_password.web_username.password
web_password = data.pass_password.web_password.password
cloudflare_key = data.pass_password.cloudflare_key.password
source = "docker"
web_username = "${var.web_username}"
web_password = "${var.web_password}"
mysql_root_password = "${var.mysql_root_password}"
cloudflare_key = "${var.cloudflare_key}"
cloudflare_email = "bb8@captnemo.in"
wiki_session_secret = data.pass_password.wiki_session_secret.password
ips = var.ips
wiki_session_secret = "${var.wiki_session_secret}"
ips = "${var.ips}"
domain = "bb8.fun"
}
module "db" {
source = "./db"
postgres-root-password = data.pass_password.postgres-root-password.password
ips = var.ips
}
module "timemachine" {
source = "./timemachine"
ips = var.ips
source = "timemachine"
ips = "${var.ips}"
username-1 = "vikalp"
password-1 = "${var.timemachine-password-1}"
username-2 = "rishav"
password-1 = data.pass_password.timemachine-password-1.password
password-2 = data.pass_password.timemachine-password-2.password
password-2 = "${var.timemachine-password-2}"
}
module "gitea" {
source = "./gitea"
domain = "git.captnemo.in"
traefik-labels = var.traefik-common-labels
ips = var.ips
secret-key = data.pass_password.gitea-secret-key.password
internal-token = data.pass_password.gitea-internal-token.password
smtp-password = data.pass_password.gitea-smtp-password.password
lfs-jwt-secret = data.pass_password.gitea-lfs-jwt-secret.password
oauth2-jwt-secret = data.pass_password.gitea-oauth2-jwt-secret.password
//passed, but not used
mysql-password = ""
traefik-network-id = module.docker.traefik-network-id
}
module "opml" {
source = "./opml"
domain = "opml.bb8.fun"
client-id = data.pass_password.opml-github-client-id.password
client-secret = data.pass_password.opml-github-client-secret.password
traefik-network-id = module.docker.traefik-network-id
source = "gitea"
domain = "git.captnemo.in"
traefik-labels = "${var.traefik-common-labels}"
ips = "${var.ips}"
secret-key = "${var.gitea-secret-key}"
internal-token = "${var.gitea-internal-token}"
smtp-password = "${var.gitea-smtp-password}"
lfs-jwt-secret = "${var.gitea-lfs-jwt-secret}"
mysql-password = "${var.gitea-mysql-password}"
}
module "radicale" {
source = "./radicale"
domain = "radicale.bb8.fun"
source = "radicale"
domain = "radicale.bb8.fun"
traefik-labels = "${var.traefik-common-labels}"
}
module "tt-rss" {
source = "tt-rss"
domain = "rss.captnemo.in"
mysql_password = "${var.mysql-ttrss-password}"
links-db = "${module.docker.names-mariadb}"
traefik-labels = "${var.traefik-common-labels}"
}
module "resilio" {
source = "resilio"
domain = "sync.bb8.fun"
traefik-labels = "${var.traefik-common-labels}"
ips = "${var.ips}"
}
module "mylar" {
source = "mylar"
domain = "mylar.bb8.fun"
traefik-labels = "${var.traefik-common-labels}"
}
module "heimdall" {
source = "heimdall"
domain = "bb8.fun"
traefik-labels = "${var.traefik-common-labels}"
auth-header = "${module.docker.auth-header}"
}
module "media" {
source = "./media"
domain = "bb8.fun"
traefik-labels = var.traefik-common-labels
ips = var.ips
# ToDO: Change this to lookup
traefik-network-id = "ffc1e366849e"
lastfm_api_key = data.pass_password.navidrome-lastfm-api-key.password
lastfm_secret = data.pass_password.navidrome-lastfm-secret.password
spotify_id = data.pass_password.navidrome-spotify-id.password
spotify_secret = data.pass_password.navidrome-spotify-secret.password
source = "media"
domain = "bb8.fun"
links-emby = "${module.docker.names-emby}"
links-transmission = "${module.docker.names-transmission}"
links-mariadb = "${module.docker.names-mariadb}"
traefik-labels = "${var.traefik-common-labels}"
airsonic-smtp-password = "${var.airsonic-smtp-password}"
airsonic-db-password = "${var.mysql_airsonic_password}"
}
module "monitoring" {
source = "./monitoring"
gf-security-admin-password = data.pass_password.gf-security-admin-password.password
source = "monitoring"
gf-security-admin-password = "${var.gf-security-admin-password}"
domain = "bb8.fun"
transmission = module.media.names-transmission
traefik-labels = var.traefik-common-labels
ips = var.ips
links-traefik = module.docker.names-traefik
traefik-network-id = module.docker.traefik-network-id
transmission = "${module.docker.names-transmission}"
traefik-labels = "${var.traefik-common-labels}"
ips = "${var.ips}"
links-traefik = "${module.docker.names-traefik}"
}
module "digitalocean" {
source = "./digitalocean"
source = "digitalocean"
}
module "home-assistant" {
source = "./home-assistant"
module "abstruse" {
source = "abstruse"
domain = "ci.bb8.fun"
traefik-labels = "${var.traefik-common-labels}"
}
module "mastodon" {
source = "./mastodon"
db-password = data.pass_password.mastodon-db-password.password
secret-key-base = data.pass_password.mastodon-secret-key-base.password
otp-secret = data.pass_password.mastodon-otp-secret.password
vapid-private-key = data.pass_password.mastodon-vapid-private-key.password
vapid-public-key = data.pass_password.mastodon-vapid-public-key.password
smtp-password = data.pass_password.mastodon-smtp-password.password
}
// Used to force access to ISP related resources
# module "tinyproxy" {
# source = "./tinyproxy"
# ips = "${var.ips}"
# }

View File

@ -1,29 +0,0 @@
module "mastodon-redis" {
name = "mastodon-redis"
source = "../modules/container"
image = "redis:alpine"
networks = ["mastodon"]
keep_image = true
resource = {
memory = 256
memory_swap = 256
}
# In case the cache dies,
# tootctl feeds build
# regenerates the feeds, run it from
# inside a mastodon container
volumes = [
{
host_path = "/mnt/zwing/cache/mastodon-redis"
container_path = "/data"
}
]
}
module "mastodon-db" {
source = "../modules/postgres"
name = "mastodon"
password = var.db-password
}

View File

@ -1,23 +0,0 @@
locals {
version = "4.1.10"
env = [
"LOCAL_DOMAIN=tatooine.club",
"REDIS_HOST=mastodon-redis",
"REDIS_PORT=6379",
"DB_HOST=postgres",
"DB_USER=mastodon",
"DB_NAME=mastodon",
"DB_PASS=${var.db-password}",
"DB_PORT=5432",
"ES_ENABLED=false",
"SECRET_KEY_BASE=${var.secret-key-base}",
"OTP_SECRET=${var.otp-secret}",
"VAPID_PRIVATE_KEY=${var.vapid-private-key}",
"VAPID_PUBLIC_KEY=${var.vapid-public-key}",
"SMTP_SERVER=smtp.eu.mailgun.org",
"SMTP_PORT=587",
"SMTP_LOGIN=mastodon@mail.tatooine.club",
"SMTP_PASSWORD=${var.smtp-password}",
"SMTP_FROM_ADDRESS=mastodon@mail.tatooine.club",
]
}

View File

@ -1,103 +0,0 @@
module "mastodon-web" {
name = "mastodon-web"
source = "../modules/container"
image = "ghcr.io/mastodon/mastodon:v${local.version}"
keep_image = true
networks = ["mastodon", "traefik", "external", "postgres"]
labels = {
"traefik.frontend.headers.STSPreload" = "true"
"traefik.frontend.headers.STSIncludeSubdomains" = "true"
"traefik.frontend.headers.STSSeconds" = "31536000"
}
env = concat(local.env,[
"MAX_THREADS=4",
"WEB_CONCURRENCY=5"
])
command = [
"bash",
"-c",
"rm -f /mastodon/tmp/pids/server.pid; bundle exec rake db:migrate; bundle exec rails s -p 3000"
]
volumes = [{
container_path = "/mastodon/public/system"
host_path = "/mnt/xwing/data/mastodon"
}]
web = {
expose = "true"
host = "tatooine.club"
port = 3000
}
resource = {
memory = 2048
memory_swap = 2048
}
}
module "mastodon-streaming" {
name = "mastodon-streaming"
source = "../modules/container"
image = "ghcr.io/mastodon/mastodon:v${local.version}"
keep_image = true
# 24 threads for Streaming
env = concat(local.env,[
"DB_POOL=8",
"STREAMING_CLUSTER_NUM=4"
])
networks = ["postgres", "external", "mastodon"]
command = [
"node",
"./streaming"
]
web = {
expose = "false"
}
resource = {
memory = 512
memory_swap = 512
}
}
module "mastodon-sidekiq" {
name = "mastodon-sidekiq"
source = "../modules/container"
image = "ghcr.io/mastodon/mastodon:v${local.version}"
keep_image = true
env = concat(local.env,[
"DB_POOL=50"
])
web = {
expose = "false"
}
networks = ["postgres", "external", "mastodon"]
command = [
"bundle",
"exec",
"sidekiq"
]
volumes = [{
container_path = "/mastodon/public/system"
host_path = "/mnt/xwing/data/mastodon"
}]
resource = {
memory = 2048
memory_swap = 2048
}
}

View File

@ -1,5 +0,0 @@
resource "docker_network" "mastodon" {
name = "mastodon"
driver = "bridge"
internal = true
}

View File

@ -1,10 +0,0 @@
terraform {
required_providers {
postgresql = {
source = "cyrilgdn/postgresql"
}
docker = {
source = "kreuzwerker/docker"
}
}
}

View File

@ -1,18 +0,0 @@
variable "db-password" {
type = string
}
variable "secret-key-base" {
type = string
}
variable "otp-secret" {
type = string
}
variable "vapid-private-key" {
type = string
}
variable "vapid-public-key" {
type = string
}
variable "smtp-password" {
type = string
}

View File

@ -1,62 +1,69 @@
# module "airsonic" {
# source = "../modules/container"
# image = "linuxserver/airsonic:latest"
# name = "airsonic"
# resource {
# memory = "1024"
# memory_swap = "1024"
# }
# web {
# port = 4040
# host = "airsonic.bb8.fun"
# expose = true
# }
# networks = "${list(docker_network.media.id, data.docker_network.bridge.id)}"
# env = [
# "PUID=1004",
# "PGID=1003",
# "TZ=Asia/Kolkata",
# "JAVA_OPTS=-Xmx512m -Dserver.use-forward-headers=true -Dserver.context-path=/",
# ]
# devices = [{
# host_path = "/dev/snd"
# container_path = "/dev/snd"
# }]
# # files = [
# # "/usr/lib/jvm/java-1.8-openjdk/jre/lib/airsonic.properties",
# # "/usr/lib/jvm/java-1.8-openjdk/jre/lib/sound.properties",
# # ]
# # contents = [
# # "${data.template_file.airsonic-properties-file.rendered}",
# # "${file("${path.module}/conf/airsonic.sound.properties")}",
# # ]
# volumes = [
# {
# host_path = "/mnt/xwing/config/airsonic2"
# container_path = "/config"
# },
# {
# host_path = "/mnt/xwing/media/Music"
# container_path = "/music"
# },
# {
# host_path = "/mnt/xwing/config/airsonic/playlists"
# container_path = "/playlists"
# },
# {
# host_path = "/mnt/xwing/config/airsonic/podcasts"
# container_path = "/podcasts"
# },
# {
# host_path = "/mnt/xwing/config/airsonic/jre"
# container_path = "/usr/lib/jvm/java-1.8-openjdk/jre/lib/"
# },
# ]
# }
# data "template_file" "airsonic-properties-file" {
# template = "${file("${path.module}/conf/airsonic.properties.tpl")}"
# vars {
# smtp-password = "${var.airsonic-smtp-password}"
# # db-password = "${var.airsonic-db-password}"
# }
# }
resource "docker_container" "airsonic" {
name = "airsonic"
image = "${docker_image.airsonic.latest}"
restart = "unless-stopped"
destroy_grace_seconds = 30
must_run = true
# Unfortunately, the --device flag is not yet supported
# in docker/terraform:
# https://github.com/terraform-providers/terraform-provider-docker/issues/30
upload {
content = "${data.template_file.airsonic-properties-file.rendered}"
file = "/usr/lib/jvm/java-1.8-openjdk/jre/lib/airsonic.properties"
}
# This lets the Jukebox use ALSA
upload {
content = "${file("${path.module}/conf/airsonic.sound.properties")}"
file = "/usr/lib/jvm/java-1.8-openjdk/jre/lib/sound.properties"
}
volumes {
host_path = "/mnt/xwing/config/airsonic/data"
container_path = "/config"
}
volumes {
host_path = "/mnt/xwing/media/Music"
container_path = "/music"
}
volumes {
host_path = "/mnt/xwing/config/airsonic/playlists"
container_path = "/playlists"
}
volumes {
host_path = "/mnt/xwing/config/airsonic/podcasts"
container_path = "/podcasts"
}
labels {
"traefik.enable" = "true"
"traefik.port" = "4040"
"traefik.frontend.rule" = "Host:airsonic.in.${var.domain},airsonic.${var.domain}"
"traefik.frontend.passHostHeader" = "true"
}
# lounge:tatooine
env = [
"PUID=1004",
"PGID=1003",
"TZ=Asia/Kolkata",
"JAVA_OPTS=-Xmx512m",
]
links = ["${var.links-mariadb}"]
}
resource "docker_image" "airsonic" {
name = "${data.docker_registry_image.airsonic.name}"
pull_triggers = ["${data.docker_registry_image.airsonic.sha256_digest}"]
}
data "docker_registry_image" "airsonic" {
name = "linuxserver/airsonic:latest"
}
data "template_file" "airsonic-properties-file" {
template = "${file("${path.module}/conf/airsonic.properties.tpl")}"
vars {
smtp-password = "${var.airsonic-smtp-password}"
db-password = "${var.airsonic-db-password}"
}
}

View File

@ -33,3 +33,9 @@ SmtpPort=465
SmtpUser=airsonic@captnemo.in
SmtpFrom=airsonic@captnemo.in
SmtpPassword=${smtp-password}
DatabaseConfigType=embed
DatabaseConfigEmbedDriver=org.hsqldb.jdbcDriver
DatabaseConfigEmbedUrl=jdbc:mysql://mariadb:3306/airsonic
DatabaseConfigEmbedUsername=airsonic
DatabaseConfigEmbedPassword=${db-password}

View File

@ -1,4 +0,0 @@
data "docker_network" "bridge" {
name = "bridge"
}

View File

@ -1,74 +0,0 @@
locals {
emby_labels = merge(var.traefik-labels, {
"traefik.frontend.rule" = "Host:emby.in.${var.domain},emby.${var.domain}"
"traefik.frontend.passHostHeader" = "true"
"traefik.port" = 8096
})
}
resource "docker_container" "emby" {
name = "emby"
image = docker_image.emby.image_id
# SSD holds both the cache and data
volumes {
host_path = "/mnt/zwing/config/emby"
container_path = "/config"
}
# We keep the cache separate
# So the config directory isn't bloated
volumes {
host_path = "/mnt/zwing/cache/emby"
container_path = "/config/cache"
}
# We want backups on the HDD
volumes {
host_path = "/mnt/xwing/backups/config/emby"
container_path = "/backups"
}
# And mount the media as well
volumes {
host_path = "/mnt/xwing/media"
container_path = "/media"
}
dynamic "labels" {
for_each = local.emby_labels
content {
label = labels.key
value = labels.value
}
}
networks = [docker_network.media.id, var.traefik-network-id]
memory = 2048
restart = "unless-stopped"
destroy_grace_seconds = 10
must_run = true
# This breaks every time we upgrade the kernel
# or the nvidia driver, and needs a reboot.
gpus = "all"
# Running as lounge:tatooine
env = [
"UID=1004",
"GID=1003",
"GIDLIST=1003"
]
}
resource "docker_image" "emby" {
name = data.docker_registry_image.emby.name
pull_triggers = [data.docker_registry_image.emby.sha256_digest]
}
data "docker_registry_image" "emby" {
name = "emby/embyserver:latest"
}

View File

@ -1,26 +1,29 @@
module "jackett" {
name = "jackett"
source = "../modules/container"
image = "linuxserver/jackett:latest"
# TODO FIXME
# networks = [data.docker_network.bridge.id]
data "docker_registry_image" "jackett" {
name = "linuxserver/jackett:latest"
}
web = {
expose = true
port = 9117
host = "jackett.${var.domain}"
}
resource "docker_image" "jackett" {
name = "${data.docker_registry_image.jackett.name}"
pull_triggers = ["${data.docker_registry_image.jackett.sha256_digest}"]
}
volumes = [
{
host_path = "/mnt/xwing/config/jackett"
container_path = "/config"
},
]
resource "docker_container" "jackett" {
name = "jackett"
image = "${docker_image.jackett.latest}"
resource = {
memory = "256"
memory_swap = "512"
labels = "${merge(
var.traefik-labels, map(
"traefik.port", 9117,
"traefik.frontend.rule","Host:jackett.${var.domain}"
))}"
restart = "unless-stopped"
destroy_grace_seconds = 10
must_run = true
volumes {
host_path = "/mnt/xwing/config/jackett"
container_path = "/config"
}
env = [
@ -28,5 +31,6 @@ module "jackett" {
"PGID=1003",
"TZ=Asia/Kolkata",
]
}
# links = ["${var.links-emby}"]
}

View File

@ -3,29 +3,19 @@ data "docker_registry_image" "lidarr" {
}
resource "docker_image" "lidarr" {
name = data.docker_registry_image.lidarr.name
pull_triggers = [data.docker_registry_image.lidarr.sha256_digest]
}
locals {
lidarr_labels = merge(var.traefik-labels, {
"traefik.port" = 8686
"traefik.frontend.rule" = "Host:lidarr.${var.domain}"
})
name = "${data.docker_registry_image.lidarr.name}"
pull_triggers = ["${data.docker_registry_image.lidarr.sha256_digest}"]
}
resource "docker_container" "lidarr" {
name = "lidarr"
image = docker_image.lidarr.image_id
dynamic "labels" {
for_each = local.lidarr_labels
content {
label = labels.key
value = labels.value
}
}
image = "${docker_image.lidarr.latest}"
labels = "${merge(
var.traefik-labels, map(
"traefik.port", 8686,
"traefik.frontend.rule","Host:lidarr.${var.domain}"
))}"
memory = 512
restart = "unless-stopped"
@ -53,6 +43,5 @@ resource "docker_container" "lidarr" {
"TZ=Asia/Kolkata",
]
networks = [docker_network.media.id, var.traefik-network-id]
links = ["${var.links-emby}", "${var.links-transmission}"]
}

View File

@ -1,50 +0,0 @@
module "navidrome" {
source = "../modules/container"
image = "deluan/navidrome"
name = "navidrome"
user = 1004
resource = {
memory = "1024"
memory_swap = "1024"
}
web = {
port = 4533
host = "music.bb8.fun"
expose = true
}
env = [
"ND_SCANINTERVAL=6h",
"ND_LOGLEVEL=info",
"ND_SESSIONTIMEOUT=300h",
"ND_BASEURL=",
"ND_AUTOIMPORTPLAYLISTS=false",
"ND_LASTFM_APIKEY=${var.lastfm_api_key}",
"ND_LASTFM_SECRET=${var.lastfm_secret}",
"ND_SPOTIFY_ID=${var.spotify_id}",
"ND_SPOTIFY_SECRET=${var.spotify_secret}",
]
# TODO FIXME
# networks = [docker_network.media.id, data.docker_network.bridge.id]
# Keep cache and data config so we can do easier backups
volumes = [
{
host_path = "/mnt/zwing/config/navidrome"
container_path = "/data"
},{
host_path = "/mnt/zwing/cache/navidrome"
container_path = "/data/cache"
},
{
host_path = "/mnt/xwing/media/Music"
container_path = "/music"
read_only = true
},
]
}

View File

@ -1,9 +0,0 @@
resource "docker_network" "media" {
name = "media"
driver = "bridge"
ipam_config {
subnet = "172.18.0.0/24"
gateway = "172.18.0.1"
}
}

View File

@ -1,8 +0,0 @@
output "names-transmission" {
value = docker_container.transmission.name
}
output "names-emby" {
value = docker_container.emby.name
}

View File

@ -1,19 +0,0 @@
terraform {
required_providers {
pass = {
source = "camptocamp/pass"
}
digitalocean = {
source = "digitalocean/digitalocean"
}
postgresql = {
source = "cyrilgdn/postgresql"
}
cloudflare = {
source = "cloudflare/cloudflare"
}
docker = {
source = "kreuzwerker/docker"
}
}
}

View File

@ -1,33 +0,0 @@
module "prowlarr" {
name = "prowlarr"
source = "../modules/container"
image = "linuxserver/prowlarr:nightly"
web = {
expose = true
port = 9696
host = "prowlarr.${var.domain}"
auth = true
}
resource = {
memory = 512
memory_swap = 1024
}
volumes = [
{
host_path = "/mnt/xwing/config/prowlarr"
container_path = "/config"
}
]
env = [
"PUID=1004",
"PGID=1003",
"TZ=Asia/Kolkata",
]
networks = [docker_network.media.id, data.docker_network.bridge.id]
}

View File

@ -1,45 +1,48 @@
module "radarr" {
name = "radarr"
source = "../modules/container"
image = "linuxserver/radarr:latest"
data "docker_registry_image" "radarr" {
name = "linuxserver/radarr:latest"
}
networks = [docker_network.media.id, data.docker_network.bridge.id]
resource "docker_image" "radarr" {
name = "${data.docker_registry_image.radarr.name}"
pull_triggers = ["${data.docker_registry_image.radarr.sha256_digest}"]
}
web = {
expose = true
port = 7878
host = "radarr.${var.domain}"
resource "docker_container" "radarr" {
name = "radarr"
image = "${docker_image.radarr.latest}"
# TODO: wildcard certs needed!
labels = "${merge(
var.traefik-labels, map(
"traefik.port", 7878,
"traefik.frontend.rule","Host:radarr.${var.domain}"
))}"
memory = 512
restart = "unless-stopped"
destroy_grace_seconds = 10
must_run = true
volumes {
host_path = "/mnt/xwing/config/radarr"
container_path = "/config"
}
resource = {
memory = 512
memory_swap = 1024
volumes {
host_path = "/mnt/xwing/media/DL"
container_path = "/downloads"
}
volumes = [
{
host_path = "/mnt/zwing/config/radarr"
container_path = "/config"
},
# Backups stay on spinning disks
{
host_path = "/mnt/xwing/backups/config/sonarr"
container_path = "/config/Backups"
},
{
host_path = "/mnt/xwing/media/DL"
container_path = "/downloads"
},
{
host_path = "/mnt/xwing/media/Movies"
container_path = "/movies"
},
]
volumes {
host_path = "/mnt/xwing/media/Movies"
container_path = "/movies"
}
env = [
"PUID=1004",
"PGID=1003",
"TZ=Asia/Kolkata",
]
}
links = ["${var.links-emby}", "${var.links-transmission}"]
}

View File

@ -1,26 +0,0 @@
module "requestrr" {
name = "requestrr"
source = "../modules/container"
image = "darkalfx/requestrr:latest"
web = {
expose = true
port = 4545
host = "requestrr.${var.domain}"
}
resource = {
memory = 256
memory_swap = 256
}
volumes = [
{
host_path = "/mnt/xwing/config/requestrr"
container_path = "/root/config"
},
]
networks = [docker_network.media.id, data.docker_network.bridge.id]
}

View File

@ -1,38 +1,41 @@
module "sonarr-container" {
name = "sonarr"
source = "../modules/container"
image = "linuxserver/sonarr:latest"
data "docker_registry_image" "sonarr" {
name = "linuxserver/sonarr:latest"
}
web = {
expose = true
port = 8989
host = "sonarr.${var.domain}"
resource "docker_image" "sonarr" {
name = "${data.docker_registry_image.sonarr.name}"
pull_triggers = ["${data.docker_registry_image.sonarr.sha256_digest}"]
}
resource "docker_container" "sonarr" {
name = "sonarr"
image = "${docker_image.sonarr.latest}"
labels = "${merge(
var.traefik-labels, map(
"traefik.port", 8989,
"traefik.frontend.rule","Host:sonarr.${var.domain}"
))}"
memory = 512
restart = "unless-stopped"
destroy_grace_seconds = 10
must_run = true
volumes {
host_path = "/mnt/xwing/config/sonarr"
container_path = "/config"
}
resource = {
memory = 512
memory_swap = 1024
volumes {
host_path = "/mnt/xwing/media/DL"
container_path = "/downloads"
}
volumes = [
{
host_path = "/mnt/zwing/config/sonarr"
container_path = "/config"
},
# Backups stay on spinning disks
{
host_path = "/mnt/xwing/backups/config/sonarr"
container_path = "/config/Backups"
},
{
host_path = "/mnt/xwing/media/DL"
container_path = "/downloads"
},
{
host_path = "/mnt/xwing/media/TV"
container_path = "/tv"
},
]
volumes {
host_path = "/mnt/xwing/media/TV"
container_path = "/tv"
}
env = [
"PUID=1004",
@ -40,6 +43,5 @@ module "sonarr-container" {
"TZ=Asia/Kolkata",
]
networks = [docker_network.media.id, data.docker_network.bridge.id]
links = ["${var.links-emby}", "${var.links-transmission}"]
}

View File

@ -1,74 +0,0 @@
locals {
transmission_labels = merge(var.traefik-labels, {
"traefik.frontend.auth.basic" = var.basic_auth
"traefik.port" = 9091
})
}
resource "docker_container" "transmission" {
name = "transmission"
image = docker_image.transmission.image_id
dynamic "labels" {
for_each = local.transmission_labels
content {
label = labels.key
value = labels.value
}
}
ports {
internal = 51413
external = 51413
ip = var.ips["eth0"]
protocol = "udp"
}
volumes {
host_path = "/mnt/xwing/config/transmission"
container_path = "/config"
}
volumes {
host_path = "/mnt/xwing/media/DL"
container_path = "/downloads"
}
volumes {
host_path = "/mnt/xwing/media/Music/Audiobooks"
container_path = "/audiobooks"
}
volumes {
host_path = "/mnt/xwing/data/watch/transmission"
container_path = "/watch"
}
upload {
content = file("${path.module}/conf/transmission.json")
file = "/config/settings.json"
}
env = [
"PGID=1003",
"PUID=1000",
"TZ=Asia/Kolkata",
]
networks = [docker_network.media.id, var.traefik-network-id]
memory = 1024
restart = "unless-stopped"
destroy_grace_seconds = 10
must_run = true
}
resource "docker_image" "transmission" {
name = data.docker_registry_image.transmission.name
pull_triggers = [data.docker_registry_image.transmission.sha256_digest]
}
data "docker_registry_image" "transmission" {
name = "linuxserver/transmission:latest"
}

View File

@ -1,42 +1,13 @@
variable "domain" {
type = string
type = "string"
}
# variable "airsonic-smtp-password" {}
variable "links-emby" {}
variable "links-transmission" {}
variable "links-mariadb" {}
variable "airsonic-smtp-password" {}
variable "airsonic-db-password" {}
variable "traefik-labels" {
type = map(string)
type = "map"
}
// TODO: Remove duplication
variable "basic_auth" {
default = "tatooine:$2y$05$iPbatint3Gulbs6kUtyALO9Yq5sBJ..aiF82bcIziH4ytz9nFoPr6,reddit:$2y$05$ghKxSydYCpAT8r2VVMDmWO/BBecghGfLsRJUkr3ii7XxPyxBqp8Oy"
}
variable "ips" {
type = map(string)
}
variable "traefik-network-id" {
}
variable "lastfm_api_key" {
description = "Navidrome Configuration for lastfm_api_key"
type = string
}
variable "lastfm_secret" {
description = "Navidrome Configuration for lastfm_secret"
type = string
}
variable "spotify_id" {
description = "Navidrome Configuration for spotify_id"
type = string
}
variable "spotify_secret" {
description = "Navidrome Configuration for spotify_secret"
type = string
}

View File

@ -1,30 +0,0 @@
module "miniflux-container" {
name = "miniflux"
source = "./modules/container"
image = "miniflux/miniflux:2.0.50"
web = {
expose = true
port = 8080
host = "rss.captnemo.in"
}
networks = ["bridge", "postgres"]
env = [
"DATABASE_URL=postgres://miniflux:${data.pass_password.miniflux-db-password.password}@postgres/miniflux?sslmode=disable",
"RUN_MIGRATIONS=1",
]
resource = {
memory = 512
memory_swap = 1024
}
}
module "miniflux-db" {
source = "./modules/postgres"
name = "miniflux"
password = data.pass_password.miniflux-db-password.password
}

Some files were not shown because too many files have changed in this diff Show More