Compare commits

..

3 Commits

Author SHA1 Message Date
Nemo fede2951c6 testing 2018-02-26 01:10:35 +05:30
Nemo 66a188df52 Add docker-tcp service 2018-02-24 20:14:33 +05:30
Nemo 6829c09331 Initial hydrogen work 2018-02-24 20:14:33 +05:30
165 changed files with 2281 additions and 4061 deletions

5
.gitignore vendored
View File

@ -3,11 +3,6 @@
.terraform .terraform
*.tfstate *.tfstate
*.tfstate.backup *.tfstate.backup
*.terraform.lock.hcl
*.out *.out
*.backup *.backup
secrets 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
````

148
README.md
View File

@ -2,106 +2,110 @@
![Nebula header image](https://cdn.spacetelescope.org/archives/images/thumb700x/heic0707a.jpg) ![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: 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/) 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/) 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/) 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/) 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/)
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> The canonical URL for this repo is https://git.captnemo.in/nemo/nebula/. A mirror is maintained on GitHub.
# modules # modules
1. docker: to actually run the services. Catch-all for miscellaneous containers 1. docker: to actually run the services. Catch-all for miscellaneous containers
2. cloudflare: to manage the DNS. 2. cloudflare: to manage the DNS.
3. mysql: to create mysql users and databases. 3. mysql: to create mysql users and databases.
4. media: Media related containers (Jackett, Lidarr, Radarr, Sonarr) 4. media: Media related containers (Jackett, Ombi, Radarr, Sonarr, Daapd)
5. Monitoring: Monitoring related resources (Cadvisor, Grafana, NodeExporter, Prometheus, Transmission-Exporter) 5. Monitoring: Monitoring related resources (Cadvisor, Grafana, NodeExporter, Prometheus, Transmission-Exporter)
6. Gitea: Just git.captnemo.in 6. Gitea: Just git.captnemo.in
7. miniflux: RSS Web reader 7. tt-rss: Tiny-Tiny RSS Web reader
8. Radicale: CardDav/CalDav webserver 8. Radicale: CardDav/CalDav webserver
Self-learning project for terraform/docker. Self-learning project for terraform/docker.
# Planned # Planned
1. ~Setup DigitalOcean~ 1. ~Setup DigitalOcean~
2. Add DO infrastructure via ansible 2. Add DO infrastructure via ansible
3. ~Add traefik for proper proxying~ 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. 4. Maybe add docker swarm (or k8s?) across both the servers. Might setup the k8s API on the Raspberry Pi.
# Service List # Service List
Currently running the following (all links are to the `store.docker.com` links for the docker images that I'm using: 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 | ## Databases
| -------------------------------- | ---------- | ---------------------------------------------------- |
| 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 |
## Docker Notes - [MariaDB](https://store.docker.com/images/mariadb) for a simple database backend
- [MongoRocks](https://store.docker.com/community/images/jadsonlourenco/mongo-rocks) as a mongoDB server. Uses RocksDB as the backend
- Lots of the above images are from the excellent [LinuxServer.io](https://www.linuxserver.io), and they're doing great work :+1: ## Media
- Most images are running the latest beta (if available) or stable versions.
- Traefik is running with wildcard certificates. - [Emby](https://store.docker.com/community/images/emby/embyserver) Media Server
- ~[CouchPotato](https://store.docker.com/community/images/linuxserver/couchpotato), auto-download movies~
- [Radarr](https://store.docker.com/community/images/linuxserver/radarr), auto-download movies
- [Sonarr](https://store.docker.com/community/images/linuxserver/sonarr), auto-download TV Shows
- [Transmission](https://store.docker.com/community/images/linuxserver/transmission), to download torrents
- [AirSonic](https://store.docker.com/community/images/airsonic/airsonic), for a music server
- [Ubooquity](https://store.docker.com/community/images/linuxserver/ubooquity), EBooks server with OPDS support
- [Lychee](https://store.docker.com/community/images/linuxserver/lychee), as a simple image-sharing/hosting service
## Plumbing
- [Traefik](https://store.docker.com/images/traefik) as a reverse-proxy server, and TLS termination
- [CAdvisor](https://store.docker.com/community/images/google/cadvisor), for basic monitoring
## Misc
- [Wiki.JS](https://store.docker.com/community/images/requarks/wiki) as a simple home-wiki
- [Muximux](https://store.docker.com/community/images/linuxserver/muximux) as a landing page for the entire setup
- [Radicale](https://store.docker.com/community/images/tomsquest/docker-radicale), for a CalDav/Carddav server
- [Gitea](https://store.docker.com/community/images/gitea/gitea), git server
Lots of the above images are from the excellent [LinuxServer.io](https://www.linuxserver.io), and they're doing great work :+1:
## Security Headers Note
The following security headers are applied using traefik on all traefik frontend docker backends:
- HSTS
- Redirect HTTP->HTTPS
- contentTypeNosniff: true
- browserXSSFilter: true
- XFO: Allow-From home.bb8.fun
- referrerPolicy: no-referrer
- X-Powered-By: Allomancy
- X-Server: BlackBox
- X-Clacks-Overhead "GNU Terry Pratchett" (On some domains)
~~Currently waiting on traefik 1.5.0-rc2 to fix security specific headers issue (marked as TODO above).~~ (Now resolved with new traefik release)
## Upstream ## 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. 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.
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: 2. Traefik docker backend security headers were broken with dashes. Reported at 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) 3. Headphones dies repeatedly with no error logs. Yet-to-report.
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: 4. Terraform doesn't parse mariadb version numbers. Report: https://github.com/terraform-providers/terraform-provider-mysql/issues/6. Got this fixed myself by filing a PR: https://github.com/hashicorp/go-version/pull/34. Another PR pending in the [provider](https://github.com/terraform-providers/terraform-provider-mysql/pull/27) to bump the go-version dependency. :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. 5. `elibsrv` didn't support ebook-convert, only mobigen. PR is at https://github.com/captn3m0/elibsrv/pull/1. I've to get this merged upstream for the 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: 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: 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: 8. Traefik Security headers don't overwrite upstream headers: https://github.com/containous/traefik/issues/2618
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: 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
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 # Plumbing
Their is a lot of additional infrastructure that is _not-yet_ part of this repo. This includes: 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. 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 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 3. Docker main configuration with half-baked CA setup
4. btrfs-backed subvolumes and snapshotting for most things in /mnt/xwing/ (in-progress) 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) 5. User-creation on the main server. (I'm using a common user for media applications and specific users for other applications)
# License # License

View File

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

View File

@ -4,18 +4,18 @@
*/ */
resource "cloudflare_record" "home" { resource "cloudflare_record" "home" {
zone_id = var.zone_id domain = "${var.domain}"
name = "in" name = "in"
value = var.ips["eth0"] value = "${var.ips["eth0"]}"
type = "A" type = "A"
} }
resource "cloudflare_record" "home-wildcard" { resource "cloudflare_record" "home-wildcard" {
zone_id = var.zone_id domain = "${var.domain}"
name = "*.in" name = "*.in"
value = cloudflare_record.home.hostname value = "${cloudflare_record.home.hostname}"
type = "CNAME" type = "CNAME"
ttl = 3600 ttl = 3600
} }
/** /**
@ -23,42 +23,18 @@ resource "cloudflare_record" "home-wildcard" {
* *.bb8.fun -> bb8.fun * *.bb8.fun -> bb8.fun
*/ */
resource "cloudflare_record" "internet" { resource "cloudflare_record" "internet" {
zone_id = var.zone_id domain = "${var.domain}"
name = "@" name = "@"
value = var.droplet_ip value = "${var.ips["static"]}"
type = "A" type = "A"
} }
resource "cloudflare_record" "internet-wildcard" { resource "cloudflare_record" "internet-wildcard" {
zone_id = var.zone_id domain = "${var.domain}"
name = var.domain name = "*.${var.domain}"
value = cloudflare_record.internet.hostname value = "${cloudflare_record.internet.hostname}"
type = "CNAME" type = "CNAME"
ttl = 3600 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"
} }
/** /**
@ -66,44 +42,18 @@ resource "cloudflare_record" "acme-no-cname-1" {
* *.vpn.bb8.fun * *.vpn.bb8.fun
*/ */
resource "cloudflare_record" "vpn" { resource "cloudflare_record" "vpn" {
zone_id = var.zone_id domain = "${var.domain}"
name = "vpn" name = "vpn"
value = var.ips["tun0"] value = "${var.ips["tun0"]}"
type = "A" type = "A"
} }
resource "cloudflare_record" "vpn_wildcard" { resource "cloudflare_record" "vpn_wildcard" {
zone_id = var.zone_id domain = "${var.domain}"
name = "*.vpn.${var.domain}" name = "*.vpn.${var.domain}"
value = cloudflare_record.vpn.hostname value = "${cloudflare_record.vpn.hostname}"
type = "CNAME" type = "CNAME"
ttl = 3600 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"
} }
######################## ########################
@ -111,21 +61,21 @@ resource "cloudflare_record" "etcd" {
######################## ########################
resource "cloudflare_record" "mailgun-spf" { resource "cloudflare_record" "mailgun-spf" {
zone_id = var.zone_id domain = "${var.domain}"
name = "l" name = "l"
value = "v=spf1 include:mailgun.org ~all" value = "v=spf1 include:mailgun.org ~all"
type = "TXT" type = "TXT"
} }
resource "cloudflare_record" "mailgun-dkim" { resource "cloudflare_record" "mailgun-dkim" {
zone_id = var.zone_id domain = "${var.domain}"
name = "k1._domainkey.l" name = "k1._domainkey.l"
value = "k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCnbP+IQkuPkgmUhpqCKzIdDSZ0HazaMp+cdBH++LBed8oY8/jmV8BhxMp5JwyePzRTxneT8ASsRtcp7CQ3z4nMC7aFX0kH6Bnu2v+u2JWudxs8x0I02OrPbSaQ5QVQdbAaCUCEfCQ06LJsn8aqPNrRIOWEMnxln+ebFJ0wKGscFQIDAQAB" value = "k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCnbP+IQkuPkgmUhpqCKzIdDSZ0HazaMp+cdBH++LBed8oY8/jmV8BhxMp5JwyePzRTxneT8ASsRtcp7CQ3z4nMC7aFX0kH6Bnu2v+u2JWudxs8x0I02OrPbSaQ5QVQdbAaCUCEfCQ06LJsn8aqPNrRIOWEMnxln+ebFJ0wKGscFQIDAQAB"
type = "TXT" type = "TXT"
} }
resource "cloudflare_record" "mailgun-mxa" { resource "cloudflare_record" "mailgun-mxa" {
zone_id = var.zone_id domain = "${var.domain}"
name = "l" name = "l"
value = "mxa.mailgun.org" value = "mxa.mailgun.org"
type = "MX" type = "MX"
@ -133,17 +83,9 @@ resource "cloudflare_record" "mailgun-mxa" {
} }
resource "cloudflare_record" "mailgun-mxb" { resource "cloudflare_record" "mailgun-mxb" {
zone_id = var.zone_id domain = "${var.domain}"
name = "l" name = "l"
value = "mxb.mailgun.org" value = "mxb.mailgun.org"
type = "MX" type = "MX"
priority = 20 priority = 20
} }
resource "cloudflare_record" "k8s" {
zone_id = var.zone_id
name = "k8s"
value = "10.8.0.1"
type = "A"
ttl = 3600
}

View File

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

View File

@ -1,10 +1,7 @@
variable "domain" { variable "domain" {
type = string type = "string"
} }
variable "ips" { 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

@ -0,0 +1,10 @@
[Unit]
Description=Docker Socket for the API
[Socket]
ListenStream=2375
BindIPv6Only=both
Service=docker.service
[Install]
WantedBy=sockets.target

View File

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

View File

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

18
digitalocean/hydrogen.tf Normal file
View File

@ -0,0 +1,18 @@
resource "digitalocean_droplet" "hydrogen" {
image = "coreos-stable"
name = "hydrogen.bb8.fun"
region = "blr1"
size = "1gb"
ipv6 = true
private_networking = true
tags = [
"bangalore",
"proxy",
"hydrogen",
"vpn",
"monitoring"
]
# user_data = "${ignition_config.hydrogen.rendered}"
}

32
digitalocean/ignition.tf Normal file
View File

@ -0,0 +1,32 @@
# Based on https://github.com/jjduhamel/tf-files/blob/master/swarm/ignition.tf
data "ignition_user" "core" {
name = "core"
no_create_home = true
groups = [ "wheel", "docker", "systemd-journal" ]
}
data "ignition_user" "nemo" {
name = "nemo"
groups = [ "wheel", "sudo", "docker", "systemd-journal" ]
ssh_authorized_keys = [
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDy8R99Ht7DVkEPW/v9/4Rf7oijC0m6/PJPNEQO9lfB340zS55cVblensxojZjkauV51vLcGfFvBCt3S/PJfZVP5isjmjqN6A7CVHc/d9+BCTepZe6TjrS/jTF+D3LoZ8xpXr7Kgf/K5Sq05XJtXfArXHJrOGBldCRHVMR/aVheDJSa0bYFsj5OhF8cOggo5vbhymgP3VbRJ0NWXDwPu5YrRiDkt02Oli9HpsR6K6CvNXeMCSBGaK/hlsRoWKM9qhtmNvb+6brCZ5MCkfF6MA395dyM9xLiAdYxudhbCfCylX7DPAFqwdrRvgLI12xM/1zsUEq8vGMJzMFnUjGhers9 nemo@flying-nemo"
]
}
data "ignition_systemd_unit" "docker-tcp" {
name = "docker-tcp.socket"
enable = true
content = "${ file("${ path.module }/docker-tcp.socket") }"
}
data "ignition_config" "hydrogen" {
systemd = [
"${ data.ignition_systemd_unit.docker-tcp.id }"
]
users = [
"${ data.ignition_user.core.id }",
"${ data.ignition_user.nemo.id }",
]
}

View File

@ -1,5 +1,4 @@
resource "digitalocean_floating_ip" "sydney" { resource "digitalocean_floating_ip" "sydney" {
droplet_id = digitalocean_droplet.sydney.id droplet_id = "${digitalocean_droplet.sydney.id}"
region = digitalocean_droplet.sydney.region 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"
}
}
}

4
digitalocean/ssh.tf Normal file
View File

@ -0,0 +1,4 @@
resource digitalocean_ssh_key "default" {
name = "Hydrogen Key"
public_key = "${file("/home/nemo/.ssh/hydrogen.pub")}"
}

1
docker/airsonic.tf Normal file
View File

@ -0,0 +1 @@

158
docker/conf/headphones.ini Normal file
View File

@ -0,0 +1,158 @@
[General]
nzb_downloader = 0
cue_split = 1
libraryscan = 1
music_encoder = 0
open_magnet_links = 0
preferred_quality = 0
customport = 5000
download_scan_interval = 5
preferred_bitrate = 320
destination_dir = /music
encodervbrcbr = cbr
xldprofile = ""
delete_lossless_files = 1
encoderquality = 2
autowant_all = 0
ignored_words = "WMA,FLAC"
freeze_db = 0
encoder_multicore_count = 0
keep_torrent_files = 0
http_root = /
download_dir = ""
http_proxy = 1
launch_browser = 0
http_username = ""
lossless_destination_dir = ""
mb_ignore_age = 365
file_underscores = 0
cue_split_flac_path = ""
lossless_bitrate_from = 0
do_not_override_git_branch = 0
include_extras = 0
samplingfrequency = 44100
http_host = 0.0.0.0
album_art_format = cover
encoder_path = ""
hpuser = ""
detect_bitrate = 0
enable_https = 0
check_github = 0
custompass = ""
mirror = musicbrainz.org
api_enabled = 0
correct_metadata = 1
customuser = ""
cue_split_shntool_path = /usr/bin/shntool
lastfm_username = captn3m0
autowant_upcoming = 1
config_version = 5
check_github_interval = 999999
customauth = 0
file_permissions = 0644
prefer_torrents = 1
encoderoutputformat = mp3
search_interval = 1440
preferred_bitrate_low_buffer = 0
ignore_clean_releases = 0
http_password = ""
usenet_retention = 1500
add_album_art = 1
headphones_indexer = 0
wait_until_release_date = 0
rename_files = 0
file_format = $Track - $Title
customhost = headphones.bb8.fun
interface = default
folder_format = $Artist/$Album
move_files = 1
cleanup_files = 1
replace_existing_folders = 0
preferred_bitrate_allow_lossless = 0
embed_album_art = 1
check_github_on_startup = 0
http_port = 8181
download_torrent_dir = /downloads
folder_permissions = 0755
official_releases_only = 0
magnet_links = 0
log_dir = /config/logs
update_db_interval = 24
git_path = ""
required_words = ""
advancedencoder = ""
numberofseeders = 5
torrentblackhole_dir = ""
cache_dir = /config/cache
blackhole = 0
libraryscan_interval = 300
keep_nfo = 0
preferred_bitrate_high_buffer = 0
https_cert = /config/server.crt
hppass = ""
customsleep = 1
api_key = ""
encoderlossless = 1
torrent_downloader = 0
torrent_removal_interval = 720
blackhole_dir = ""
keep_original_folder = 1
extras = ""
autowant_manually_added = 1
encoder_multicore = 0
encoderfolder = ""
preferred_words = ""
https_key = /config/server.key
encoder = ffmpeg
git_user = rembo10
bitrate = 192
music_dir = /music
auto_add_artists = 1
git_branch = master
embed_lyrics = 0
lossless_bitrate_to = 0
keep_torrent_files_dir = ""
file_permissions_enabled = 1
album_art_max_width = 512
album_art_min_width = 512
soft_chroot = ""
rename_unprocessed = 1
rename_frozen = 1
folder_permissions_enabled = 1
do_not_process_unmatched = 0
[Subsonic]
subsonic_host = ""
subsonic_password = ""
subsonic_enabled = 0
subsonic_username = ""
[Email]
email_onsnatch = 0
email_smtp_password = ""
email_tls = 0
email_smtp_port = 25
email_smtp_server = ""
email_enabled = 0
email_smtp_user = ""
email_ssl = 0
email_to = ""
email_from = ""
[Advanced]
verify_ssl_cert = 1
ignored_files = ,
journal_mode = wal
album_completion_pct = 80
ignored_folders = ,
cache_sizemb = 32
[Piratebay]
piratebay_ratio = 0.1
piratebay = 1
piratebay_proxy_url = https://duckingproxy.eu/
[MPC]
mpc_enabled = 0
[XBMC]
xbmc_username = ""
xbmc_host = http://${var.ips["eth0"]}:8080
xbmc_enabled = 1
xbmc_update = 1
xbmc_password = ""
xbmc_notify = 1

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,11 +1,12 @@
defaultEntryPoints = ["http", "https"] defaultEntryPoints = ["http", "https"]
sendAnonymousUsage = true
checkNewVersion = false
[traefikLog] InsecureSkipVerify = true
[accessLog]
[entryPoints] [entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.http.redirect]
entryPoint = "https"
[entryPoints.https] [entryPoints.https]
address = ":443" address = ":443"
# This is required for ACME support # This is required for ACME support
@ -16,15 +17,9 @@ checkNewVersion = false
[[entryPoints.https.tls.certificates]] [[entryPoints.https.tls.certificates]]
certFile = "/etc/traefik/rss.captnemo.in.crt" certFile = "/etc/traefik/rss.captnemo.in.crt"
keyFile = "/etc/traefik/rss.captnemo.in.key" keyFile = "/etc/traefik/rss.captnemo.in.key"
[[entryPoints.https.tls.certificates]]
certFile = "/etc/traefik/tatooine.club.crt"
keyFile = "/etc/traefik/tatooine.club.key"
[docker] [docker]
# Make sure you mount this as readonly # 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" endpoint = "unix:///var/run/docker.sock"
domain = "bb8.fun" domain = "bb8.fun"
watch = true watch = true
@ -37,6 +32,33 @@ checkNewVersion = false
# Since I can't apply a authentication # Since I can't apply a authentication
# on this yet # 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] [web]
address = ":1111" address = ":1111"
readOnly = true readOnly = true
@ -45,6 +67,7 @@ checkNewVersion = false
[web.metrics.prometheus] [web.metrics.prometheus]
[acme] [acme]
email = "acme@captnemo.in" email = "acme@captnemo.in"
storage = "/acme/acme.json" storage = "/acme/acme.json"
entryPoint = "https" entryPoint = "https"
@ -55,14 +78,46 @@ acmelogging = true
[acme.httpChallenge] [acme.httpChallenge]
entryPoint = "http" entryPoint = "http"
[acme.dnsChallenge] # Keep DNS challenge disabled
provider = "cloudflare" # for now
delayBeforeCheck = 120 # [acme.dnsChallenge]
resolvers = ["1.1.1.1:53", "8.8.8.8:53"] # provider = "cloudflare"
# delayBeforeCheck = 5
# Get wildcard once possible
# Primary 2 wildcard certs
[[acme.domains]] [[acme.domains]]
main = "*.bb8.fun" main = "bb8.fun"
# Internal services are also protected! sans = [
[[acme.domains]] "ads.bb8.fun",
main = "*.in.bb8.fun" "airsonic.bb8.fun",
"apps.bb8.fun",
"cadvisor.bb8.fun",
"debug.in.bb8.fun",
"dns.bb8.fun",
"emby.bb8.fun",
"emby.in.bb8.fun",
"falcon.bb8.fun",
"ghost.bb8.fun",
"grafana.bb8.fun",
"headphones.bb8.fun",
"home.bb8.fun",
"info.bb8.fun",
"jackett.bb8.fun",
"library.bb8.fun",
"luke.bb8.fun",
"monitoring.bb8.fun",
"ombi.bb8.fun",
"pics.bb8.fun",
"pics.in.bb8.fun",
"radarr.bb8.fun",
"read.bb8.fun",
"rey.bb8.fun",
"scan.bb8.fun",
"sonarr.bb8.fun",
"tatooine.bb8.fun",
"tie.bb8.fun",
"traefik.bb8.fun",
"transmission.bb8.fun",
"wifi.bb8.fun",
"wiki.bb8.fun"
]

View File

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

View File

@ -3,22 +3,8 @@
{ {
"pathString": "/files", "pathString": "/files",
"userName": [ "userName": [
"arvind",
"diya",
"gappan",
"himanshu",
"konarak",
"pratyush",
"reddit", "reddit",
"riccu", "tatooine"
"sankalp",
"shreyas",
"tatooine",
"vignesh",
"harman",
"pranav",
"swapnil",
"noopur"
] ]
} }
], ],
@ -26,22 +12,8 @@
{ {
"pathString": "/comics", "pathString": "/comics",
"userName": [ "userName": [
"arvind",
"diya",
"gappan",
"himanshu",
"konarak",
"pratyush",
"reddit", "reddit",
"riccu", "tatooine"
"sankalp",
"shreyas",
"tatooine",
"vignesh",
"harman",
"pranav",
"swapnil",
"noopur"
] ]
} }
], ],
@ -49,139 +21,51 @@
{ {
"pathString": "/books", "pathString": "/books",
"userName": [ "userName": [
"arvind",
"diya",
"gappan",
"himanshu",
"konarak",
"pratyush",
"reddit", "reddit",
"riccu", "tatooine"
"sankalp",
"shreyas",
"tatooine",
"vignesh",
"harman",
"pranav",
"swapnil",
"noopur"
] ]
} }
], ],
"users": [ "users": [
{ {
"name": "reddit", "name": "reddit",
"passwordHash": "passwordHash": "396731fff7f1931aeba6e69d3443d5ef7971569e3b9d64a3a4deca655789917a"
"396731fff7f1931aeba6e69d3443d5ef7971569e3b9d64a3a4deca655789917a"
}, },
{ {
"name": "tatooine", "name": "tatooine",
"passwordHash": "passwordHash": "ca0c540641a9e34c47cbd1866443ca181202aaa422fcc5ad4cbf75095aab7da0"
"ca0c540641a9e34c47cbd1866443ca181202aaa422fcc5ad4cbf75095aab7da0"
},
{
"name": "riccu",
"passwordHash":
"ff66d15e21624763cb2d65a21a7aa275ae65219d6f5ed0e5c5583c9be2fc3b12"
},
{
"name": "sankalp",
"passwordHash":
"b3c219dffa8a379c4daaed75c63141ebefa2a6f0a872e9cd7f328ad6511fb863"
},
{
"name": "pratyush",
"passwordHash":
"e63af1a184949abfd3666ef2c60c462191619fdcefadf9021a5d24f236d302fe"
},
{
"name": "arvind",
"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"
} }
], ],
"isFilesProviderEnabled" : true, "isFilesProviderEnabled": true,
"isComicsProviderEnabled" : true, "isComicsProviderEnabled": true,
"isBooksProviderEnabled" : true, "isBooksProviderEnabled": true,
"isUserManagementEnabled" : true, "isUserManagementEnabled": true,
"libraryPortNumber" : 2202, "libraryPortNumber": 2202,
"adminPortNumber" : 2203, "adminPortNumber": 2203,
"comicWidth" : 160, "comicWidth": 160,
"comicHeight" : 230, "comicHeight": 230,
"comicsPaginationNumber" : 30, "comicsPaginationNumber": 30,
"bookWidth" : 160, "bookWidth": 160,
"bookHeight" : 230, "bookHeight": 230,
"booksPaginationNumber" : 30, "booksPaginationNumber": 30,
"minimizeToTray" : false, "minimizeToTray": false,
"minimizeOnStartup" : false, "minimizeOnStartup": false,
"autoscanPeriod" : 1440, "autoscanPeriod": 0,
"isRemoteAdminEnabled" : true, "isRemoteAdminEnabled": true,
"theme" : "default", "theme": "default",
"isShrinkingCacheEnabled" : false, "isShrinkingCacheEnabled": false,
"shrunkPageWidth" : 1536, "shrunkPageWidth": 1536,
"shrunkPageHeight" : 2500, "shrunkPageHeight": 2500,
"shrinkingCachePath" : "", "shrinkingCachePath": "",
"autoScanAtLaunch" : false, "autoScanAtLaunch": false,
"reverseProxyPrefix" : "", "reverseProxyPrefix": "",
"keystorePath" : "", "keystorePath": "",
"keystorePassword" : "", "keystorePassword": "",
"isOpdsProviderEnabled" : true, "isOpdsProviderEnabled": true,
"folderExclusionPattern" : "", "folderExclusionPattern": "",
"bypassSingleRootFolder" : false, "bypassSingleRootFolder": false,
"enableFolderMetadataDisplay" : true, "enableFolderMetadataDisplay": true,
"bookmarkUsingCookies" : false, "bookmarkUsingCookies": false,
"displayTitleInsteadOfFileName" : true, "displayTitleInsteadOfFileName": true,
"keepUnreachableSharedFolders" : false, "keepUnreachableSharedFolders": false
"isCalibreLibrary" : false,
"instanceId" : "3a0e4425a8e14c719ca2eb382f85292e"
} }

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,45 @@
# Database versions shouldn't be upgraded
data "docker_registry_image" "mariadb" {
name = "mariadb:10.3"
}
data "docker_registry_image" "mongorocks" {
name = "jadsonlourenco/mongo-rocks:latest"
}
data "docker_registry_image" "emby" {
name = "emby/embyserver:latest"
}
data "docker_registry_image" "transmission" {
name = "linuxserver/transmission:latest"
}
data "docker_registry_image" "traefik" { data "docker_registry_image" "traefik" {
name = "traefik:1.7" name = "traefik:cancoillotte-alpine"
}
data "docker_registry_image" "wikijs" {
name = "requarks/wiki:latest"
}
data "docker_registry_image" "headphones" {
name = "linuxserver/headphones:latest"
}
data "docker_registry_image" "muximux" {
name = "linuxserver/muximux:latest"
} }
data "docker_registry_image" "ubooquity" { data "docker_registry_image" "ubooquity" {
name = "linuxserver/ubooquity:latest" name = "linuxserver/ubooquity:latest"
} }
data "docker_registry_image" "headerdebug" {
name = "brndnmtthws/nginx-echo-headers:latest"
}
data "docker_registry_image" "lychee" { data "docker_registry_image" "lychee" {
name = "linuxserver/lychee:latest" name = "linuxserver/lychee:latest"
} }

56
docker/db.tf Normal file
View File

@ -0,0 +1,56 @@
resource "docker_container" "mongorocks" {
name = "mongorocks"
image = "${docker_image.mongorocks.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}"
}
env = [
"AUTH=no",
"DATABASE=wiki",
"OPLOG_SIZE=50",
]
}
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}",
]
}

18
docker/debug.tf Normal file
View File

@ -0,0 +1,18 @@
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
# }

43
docker/headphones.tf Normal file
View File

@ -0,0 +1,43 @@
resource "docker_container" "headphones" {
name = "headphones"
image = "${docker_image.headphones.latest}"
restart = "unless-stopped"
destroy_grace_seconds = 10
must_run = true
memory = 128
volumes {
host_path = "/mnt/xwing/config/headphones"
container_path = "/config"
}
volumes {
host_path = "/mnt/xwing/media/DL"
container_path = "/downloads"
}
volumes {
host_path = "/mnt/xwing/media/Music"
container_path = "/music"
}
upload {
content = "${file("${path.module}/conf/headphones.ini")}"
file = "/config/config.ini"
}
labels = "${merge(
local.traefik_common_labels,
map(
"traefik.frontend.auth.basic", "${var.basic_auth}",
"traefik.port", 8181,
))}"
# lounge:tatooine
env = [
"PUID=1004",
"PGID=1003",
"TZ=Asia/Kolkata",
]
}

View File

@ -1,14 +1,59 @@
resource "docker_image" "traefik17" { resource "docker_image" "emby" {
name = data.docker_registry_image.traefik.name name = "${data.docker_registry_image.emby.name}"
pull_triggers = [data.docker_registry_image.traefik.sha256_digest] 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" "traefik" {
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}"]
}
# Attempting to use mongorocks to work around reboot issue
# Hoping that this will not face reboot-recovery issues
# Wrote about this: https://captnemo.in/blog/2017/12/18/home-server-learnings/
resource "docker_image" "mongorocks" {
name = "${data.docker_registry_image.mongorocks.name}"
pull_triggers = ["${data.docker_registry_image.mongorocks.sha256_digest}"]
}
resource "docker_image" "headphones" {
name = "${data.docker_registry_image.headphones.name}"
pull_triggers = ["${data.docker_registry_image.headphones.sha256_digest}"]
}
resource "docker_image" "muximux" {
name = "${data.docker_registry_image.muximux.name}"
pull_triggers = ["${data.docker_registry_image.muximux.sha256_digest}"]
} }
resource "docker_image" "ubooquity" { resource "docker_image" "ubooquity" {
name = data.docker_registry_image.ubooquity.name name = "${data.docker_registry_image.ubooquity.name}"
pull_triggers = [data.docker_registry_image.ubooquity.sha256_digest] pull_triggers = ["${data.docker_registry_image.ubooquity.sha256_digest}"]
} }
# resource "docker_image" "lychee" { # Helps debug traefik reverse proxy headers
# name = "${data.docker_registry_image.lychee.name}" # Highly recommended!
# pull_triggers = ["${data.docker_registry_image.lychee.sha256_digest}"] 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

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

View File

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

1
docker/main.tf Normal file
View File

@ -0,0 +1 @@

31
docker/muximux.tf Normal file
View File

@ -0,0 +1,31 @@
resource "docker_container" "muximux" {
name = "muximux"
image = "${docker_image.muximux.latest}"
memory = 64
restart = "unless-stopped"
destroy_grace_seconds = 10
must_run = true
volumes {
host_path = "/mnt/xwing/config/muximux"
container_path = "/config"
}
labels = "${merge(
local.traefik_common_labels,
map(
"traefik.port", 80,
"traefik.frontend.headers.frameDeny", "true",
"traefik.frontend.passHostHeader", "false",
"traefik.frontend.auth.basic", "${var.basic_auth}",
"traefik.frontend.rule", "Host:home.in.${var.domain},home.${var.domain}",
))}"
# lounge:tatooine
env = [
"PUID=1004",
"PGID=1003",
"TZ=Asia/Kolkata",
]
}

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" { output "lychee-ip" {
# value = "${docker_container.lychee.ip_address}" value = "${docker_container.lychee.ip_address}"
# }
output "names-traefik" {
value = docker_container.traefik.name
} }
output "traefik-network-id" { output "names-transmission" {
value = docker_network.traefik.id 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" { 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,70 @@
resource "docker_container" "traefik" { resource "docker_container" "traefik" {
name = "traefik" name = "traefik"
image = docker_image.traefik17.image_id image = "${docker_image.traefik.latest}"
# Admin Backend
labels { ports {
label = "traefik.enable" internal = 1111
value = "true" external = 1111
ip = "${var.ips["eth0"]}"
} }
labels { ports {
label = "traefik.http.routers.api.rule" internal = 1111
value = "Host('traefik.in.bb8.fun')" external = 1111
} ip = "${var.ips["tun0"]}"
labels {
label = "traefik.http.routers.api.service"
value = "api@internal"
} }
# Local Web Server # Local Web Server
ports { ports {
internal = 80 internal = 80
external = 80 external = 80
ip = var.ips["eth0"] ip = "${var.ips["eth0"]}"
} }
# Local Web Server (HTTPS) # Local Web Server (HTTPS)
ports { ports {
internal = 443 internal = 443
external = 443 external = 443
ip = var.ips["eth0"] ip = "${var.ips["eth0"]}"
} }
# Proxied via sydney.captnemo.in # Proxied via sydney.captnemo.in
ports { ports {
internal = 443 internal = 443
external = 443 external = 443
ip = var.ips["tun0"] ip = "${var.ips["tun0"]}"
} }
ports { ports {
internal = 80 internal = 80
external = 80 external = 80
ip = var.ips["tun0"] ip = "${var.ips["tun0"]}"
} }
upload { upload {
content = file("${path.module}/conf/traefik.toml") content = "${file("${path.module}/conf/traefik.toml")}"
file = "/etc/traefik/traefik.toml" file = "/etc/traefik/traefik.toml"
} }
upload { upload {
content = file( content = "${file("/home/nemo/projects/personal/certs/git.captnemo.in/fullchain.pem")}"
"/home/nemo/projects/personal/certs/git.captnemo.in/fullchain.pem", file = "/etc/traefik/git.captnemo.in.crt"
)
file = "/etc/traefik/git.captnemo.in.crt"
} }
upload { upload {
content = file( content = "${file("/home/nemo/projects/personal/certs/git.captnemo.in/privkey.pem")}"
"/home/nemo/projects/personal/certs/git.captnemo.in/privkey.pem", file = "/etc/traefik/git.captnemo.in.key"
)
file = "/etc/traefik/git.captnemo.in.key"
} }
upload { upload {
content = file( content = "${file("/home/nemo/projects/personal/certs/rss.captnemo.in/fullchain.pem")}"
"/home/nemo/projects/personal/certs/lego/certificates/tatooine.club.key", file = "/etc/traefik/rss.captnemo.in.crt"
)
file = "/etc/traefik/tatooine.club.key"
} }
upload { upload {
content = file( content = "${file("/home/nemo/projects/personal/certs/rss.captnemo.in/privkey.pem")}"
"/home/nemo/projects/personal/certs/lego/certificates/tatooine.club.crt", file = "/etc/traefik/rss.captnemo.in.key"
)
file = "/etc/traefik/tatooine.club.crt"
}
upload {
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/rss.captnemo.in/privkey.pem",
)
file = "/etc/traefik/rss.captnemo.in.key"
} }
volumes { volumes {
@ -104,20 +79,10 @@ resource "docker_container" "traefik" {
} }
memory = 256 memory = 256
restart = "always" restart = "unless-stopped"
destroy_grace_seconds = 10 destroy_grace_seconds = 10
must_run = true 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 = [ env = [
"CLOUDFLARE_EMAIL=${var.cloudflare_email}", "CLOUDFLARE_EMAIL=${var.cloudflare_email}",
"CLOUDFLARE_API_KEY=${var.cloudflare_key}", "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" { resource "docker_container" "ubooquity" {
name = "ubooquity" name = "ubooquity"
image = docker_image.ubooquity.image_id image = "${docker_image.ubooquity.latest}"
restart = "unless-stopped" restart = "unless-stopped"
destroy_grace_seconds = 30 destroy_grace_seconds = 30
@ -32,37 +25,28 @@ resource "docker_container" "ubooquity" {
host_path = "/mnt/xwing/media/EBooks/Comics" host_path = "/mnt/xwing/media/EBooks/Comics"
container_path = "/comics" container_path = "/comics"
} }
labels { labels {
label = "traefik.enable" "traefik.enable" = "true"
value = "true"
} "traefik.admin.port" = 2203
labels { "traefik.admin.frontend.rule" = "Host:library.${var.domain}"
label = "traefik.admin.port" "traefik.admin.frontend.auth.basic" = "${var.basic_auth}"
value = 2203
} "traefik.read.port" = 2202
labels { "traefik.read.frontend.rule" = "Host:read.${var.domain}"
label = "traefik.admin.frontend.rule"
value = "Host:library.${var.domain}" "traefik.read.frontend.headers.SSLTemporaryRedirect" = "true"
} "traefik.read.frontend.headers.STSSeconds" = "2592000"
labels { "traefik.read.frontend.headers.STSIncludeSubdomains" = "false"
label = "traefik.admin.frontend.auth.basic" "traefik.read.frontend.headers.contentTypeNosniff" = "true"
value = var.basic_auth "traefik.read.frontend.headers.browserXSSFilter" = "true"
} "traefik.read.frontend.headers.customResponseHeaders" = "${var.xpoweredby}"
labels { "traefik.frontend.headers.customFrameOptionsValue" = "${var.xfo_allow}"
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"
} }
upload { upload {
content = file("${path.module}/conf/ubooquity.json") content = "${file("${path.module}/conf/ubooquity.json")}"
file = "/config/preferences.json" file = "/config/preferences.json"
} }
@ -73,4 +57,3 @@ resource "docker_container" "ubooquity" {
"MAXMEM=800", "MAXMEM=800",
] ]
} }

View File

@ -1,18 +1,22 @@
variable "web_username" { variable "web_username" {
type = string type = "string"
} }
variable "web_password" { variable "web_password" {
type = string type = "string"
}
variable "mysql_root_password" {
type = "string"
} }
variable "cloudflare_key" { variable "cloudflare_key" {
type = string type = "string"
description = "cloudflare API Key" description = "cloudflare API Key"
} }
variable "cloudflare_email" { variable "cloudflare_email" {
type = string type = "string"
description = "cloudflare email address" description = "cloudflare email address"
} }
@ -39,15 +43,13 @@ variable "refpolicy" {
} }
variable "wiki_session_secret" { variable "wiki_session_secret" {
type = string type = "string"
} }
variable "domain" { variable "domain" {
type = string type = "string"
} }
variable "ips" { variable "ips" {
type = map(string) type = "map"
} }
# variable "links-mariadb" {}

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

@ -1,27 +1,19 @@
; This file lists the default values used by Gitea ; This file lists the default values used by Gitea
; Copy required sections to your own app.ini (default is custom/conf/app.ini) ; Copy required sections to your own app.ini (default is custom/conf/app.ini)
; and modify as needed. ; 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 that shows on every page title
APP_NAME = Nemo's code APP_NAME = Nemo's code
RUN_MODE = prod RUN_MODE = prod
RUN_USER = git RUN_USER = git
WORK_PATH=/data/gitea
[repository] [repository]
ROOT = /data/git/repositories ROOT = /data/git/repositories
USE_COMPAT_SSH_URI = false
[repository.upload] [repository.upload]
TEMP_PATH = /data/gitea/uploads TEMP_PATH = /data/gitea/uploads
[ui] [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 ; Value of `theme-color` meta tag, used by Android >= 5.0
; An invalid color like "none" or "disable" will have the default style ; 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 ; More info: https://developers.google.com/web/updates/2014/11/Support-for-theme-color-in-Chrome-39-for-Android
@ -41,11 +33,6 @@ NOTICE_PAGING_NUM = 25
; Number of organization that are showed in one page ; Number of organization that are showed in one page
ORG_PAGING_NUM = 50 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] [ui.user]
; Number of repos that are showed in one page ; Number of repos that are showed in one page
REPO_PAGING_NUM = 15 REPO_PAGING_NUM = 15
@ -60,12 +47,11 @@ KEYWORDS = git, captnemo, git.captnemo.in, piratecoders
ENABLE_HARD_LINE_BREAK = false ENABLE_HARD_LINE_BREAK = false
; List of custom URL-Schemes that are allowed as links when rendering Markdown ; List of custom URL-Schemes that are allowed as links when rendering Markdown
; for example git,magnet ; for example git,magnet
CUSTOM_URL_SCHEMES = git,magnet,steam,irc,slack CUSTOM_URL_SCHEMES = git,magnet,steam
; List of file extensions that should be rendered/edited as Markdown
; Separate extensions with a comma. To render files w/o extension as markdown, just put a comma
FILE_EXTENSIONS = .md,.markdown,.mdown,.mkd 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) ; Define allowed algorithms and their minimum key length (use -1 to disable a type)
[ssh.minimum_key_sizes] [ssh.minimum_key_sizes]
ED25519 = 256 ED25519 = 256
@ -73,48 +59,49 @@ ECDSA = 256
RSA = 2048 RSA = 2048
DSA = 1024 DSA = 1024
[lfs]
PATH=/data/gitea/lfs
[server] [server]
APP_DATA_PATH = /data/gitea APP_DATA_PATH = /data/gitea
SSH_DOMAIN = git.captnemo.in
HTTP_PORT = 3000 HTTP_PORT = 3000
ROOT_URL = https://git.captnemo.in/ ROOT_URL = https://git.captnemo.in/
DISABLE_SSH = true DISABLE_SSH = false
SSH_PORT = 22
DOMAIN = git.captnemo.in DOMAIN = git.captnemo.in
LFS_START_SERVER = true LFS_START_SERVER = true
LFS_JWT_SECRET = "${lfs-jwt-secret}" LFS_CONTENT_PATH = /data/gitea/lfs
LFS_JWT_SECRET = nsLco71Wn4iu_UzyDir0jzkCdJDya1L9N0KZfgew13E
OFFLINE_MODE = true OFFLINE_MODE = true
LANDING_PAGE = explore
MINIMUM_KEY_SIZE_CHECK = true
# Uses the Mozilla Modern SSH Config params
SSH_SERVER_CIPHERS = chacha20-poly1305@openssh.com, aes256-gcm@openssh.com, aes128-gcm@openssh.com, aes256-ctr, aes192-ctr, aes128-ctr
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] [database]
; TODO ; TODO
; ; Either "mysql", "postgres", "mssql" or "sqlite3", it's your choice ; ; Either "mysql", "postgres", "mssql" or "sqlite3", it's your choice
DB_TYPE = sqlite3 ; DB_TYPE = mysql
HOST = mariadb:3306 ; HOST = 127.0.0.1:3306
NAME = gitea ; NAME = gitea
USER = gitea ; USER = root
; PASSWD = "mysql-password" ; PASSWD =
; ; For "postgres" only, either "disable", "require" or "verify-full" ; ; For "postgres" only, either "disable", "require" or "verify-full"
; SSL_MODE = disable ; SSL_MODE = disable
; ; For "sqlite3" and "tidb", use absolute path when you start as service ; ; For "sqlite3" and "tidb", use absolute path when you start as service
PATH = /data/gitea/gitea.db ; PATH = data/gitea.db
; ; For "sqlite3" only. Query timeout ; ; For "sqlite3" only. Query timeout
SQLITE_TIMEOUT = 500 ; SQLITE_TIMEOUT = 500
; ; For iterate buffer, default is 50 ; ; For iterate buffer, default is 50
; ITERATE_BUFFER_SIZE = 50 ; ITERATE_BUFFER_SIZE = 50
; Show the database generated SQL
LOG_SQL = false PATH = /data/gitea/gitea.db
SQLITE_JOURNAL_MODE = WAL DB_TYPE = sqlite3
HOST = localhost:3306
NAME = gitea
USER = root
PASSWD =
SSL_MODE = disable
[session]
PROVIDER_CONFIG = /data/gitea/sessions
PROVIDER = file
[picture] [picture]
AVATAR_UPLOAD_PATH = /data/gitea/avatars AVATAR_UPLOAD_PATH = /data/gitea/avatars
@ -124,25 +111,33 @@ ENABLE_FEDERATED_AVATAR = false
[indexer] [indexer]
ISSUE_INDEXER_PATH = indexers/issues.bleve ISSUE_INDEXER_PATH = indexers/issues.bleve
; repo indexer by default disabled, since it uses a lot of disk space ; repo indexer by default disabled, since it uses a lot of disk space
REPO_INDEXER_ENABLED = true REPO_INDEXER_ENABLED = false
REPO_INDEXER_PATH = indexers/repos.bleve REPO_INDEXER_PATH = indexers/repos.bleve
UPDATE_BUFFER_LEN = 20
MAX_FILE_SIZE = 1048576 MAX_FILE_SIZE = 1048576
[queue.issue_indexer]
LENGTH = 100
[admin] [admin]
; Disable regular (non-admin) users to create organizations ; Disable regular (non-admin) users to create organizations
DISABLE_REGULAR_ORG_CREATION = false DISABLE_REGULAR_ORG_CREATION = false
[security] [security]
; Whether the installer is disabled
INSTALL_LOCK = true INSTALL_LOCK = true
; Auto-login remember days
LOGIN_REMEMBER_DAYS = 30 LOGIN_REMEMBER_DAYS = 30
; COOKIE_USERNAME = gitea_awesome
; COOKIE_REMEMBER_NAME = gitea_incredible
; Reverse proxy authentication header name of user name
; REVERSE_PROXY_AUTHENTICATION_USER = X-WEBAUTH-USER
; Sets the minimum password length for new Users
MIN_PASSWORD_LENGTH = 10 MIN_PASSWORD_LENGTH = 10
IMPORT_LOCAL_PATHS = true ; True when users are allowed to import local server paths
IMPORT_LOCAL_PATHS = false
; Prevent all users (including admin) from creating custom git hooks
DISABLE_GIT_HOOKS = true DISABLE_GIT_HOOKS = true
SECRET_KEY = "${secret_key}"
INTERNAL_TOKEN = "${internal_token}" SECRET_KEY = ${secret_key}
INTERNAL_TOKEN = ${internal_token}
[service] [service]
; ; More detail: https://github.com/gogits/gogs/issues/165 ; ; More detail: https://github.com/gogits/gogs/issues/165
@ -155,16 +150,14 @@ ACTIVE_CODE_LIVE_MINUTES = 15
RESET_PASSWD_CODE_LIVE_MINUTES = 30 RESET_PASSWD_CODE_LIVE_MINUTES = 30
REGISTER_EMAIL_CONFIRM = true REGISTER_EMAIL_CONFIRM = true
ENABLE_NOTIFY_MAIL = true ENABLE_NOTIFY_MAIL = true
DISABLE_REGISTRATION = true DISABLE_REGISTRATION = false
; ; Enable captcha validation for registration ; ; Enable captcha validation for registration
ENABLE_CAPTCHA = true ENABLE_CAPTCHA = true
REQUIRE_EXTERNAL_REGISTRATION_CAPTCHA = true
CAPTCHA_TYPE = image
; ; User must sign in to view anything. ; ; User must sign in to view anything.
REQUIRE_SIGNIN_VIEW = false REQUIRE_SIGNIN_VIEW = false
; ; Default value for KeepEmailPrivate ; ; Default value for KeepEmailPrivate
; ; New user will get the value of this setting copied into their profile ; ; 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 ; ; Default value for AllowCreateOrganization
; ; New user will have rights set to create organizations depending on this setting ; ; New user will have rights set to create organizations depending on this setting
DEFAULT_ALLOW_CREATE_ORGANIZATION = true DEFAULT_ALLOW_CREATE_ORGANIZATION = true
@ -177,59 +170,174 @@ NO_REPLY_ADDRESS = noreply.example.org
ENABLE_REVERSE_PROXY_AUTHENTICATION = false ENABLE_REVERSE_PROXY_AUTHENTICATION = false
ENABLE_REVERSE_PROXY_AUTO_REGISTRATION = false ENABLE_REVERSE_PROXY_AUTO_REGISTRATION = false
; [webhook]
; ; Hook task queue length, increase if webhook shooting starts hanging
; QUEUE_LENGTH = 1000
; ; Deliver timeout in seconds
; DELIVER_TIMEOUT = 5
; ; Allow insecure certification
; SKIP_TLS_VERIFY = false
; ; Number of history information in each page
; PAGING_NUM = 10
[mailer] [mailer]
ENABLED = true ENABLED = true
; ; Buffer length of channel, keep it as it is if you don't know what it is.
; SEND_BUFFER_LEN = 100
; ; Name displayed in mail title
; SUBJECT = %(APP_NAME)s
; ; Mail server
; ; Gmail: smtp.gmail.com:587
; ; QQ: smtp.qq.com:465
; ; Note, if the port ends with "465", SMTPS will be used. Using STARTTLS on port 587 is recommended per RFC 6409. If the server supports STARTTLS it will always be used.
HOST = smtp.migadu.com:587
; ; Disable HELO operation when hostname are different.
; DISABLE_HELO =
; ; Custom hostname for HELO operation, default is from system.
; HELO_HOSTNAME =
; ; Do not verify the certificate of the server. Only use this for self-signed certificates
; SKIP_VERIFY =
; ; Use client certificate
; USE_CERTIFICATE = false
; CERT_FILE = custom/mailer/cert.pem
; KEY_FILE = custom/mailer/key.pem
; ; Mail from address, RFC 5322. This can be just an email address, or the `"Name" <email@example.com>` format
FROM = git@captnemo.in FROM = git@captnemo.in
; ; Mailer user name and password
USER = git@captnemo.in USER = git@captnemo.in
PASSWD = ${smtp_password} PASSWD = ${smtp_password}
PROTOCOL = smtps ; ; Send mails as plain text
SMTP_ADDR = smtp.migadu.com
SMTP_PORT = 465
SEND_AS_PLAIN_TEXT = true SEND_AS_PLAIN_TEXT = true
SUBJECT_PREFIX = "[git.captnemo.in] " ; ; Enable sendmail (override SMTP)
; USE_SENDMAIL = false
; ; Specify an alternative sendmail binary
; SENDMAIL_PATH = sendmail
; ; Specify any extra sendmail arguments
; SENDMAIL_ARGS =
[cache] ; [cache]
ADAPTER = redis ; ; Either "memory", "redis", or "memcache", default is "memory"
HOST = "network=tcp,addr=gitea-redis:6379,db=0,pool_size=100,idle_timeout=180" ; ADAPTER = memory
; ; For "memory" only, GC interval in seconds, default is 60
; INTERVAL = 60
; ; For "redis" and "memcache", connection host address
; ; redis: network=tcp,addr=:6379,password=macaron,db=0,pool_size=100,idle_timeout=180
; ; memcache: `127.0.0.1:11211`
; HOST =
; ; Time to keep items in cache if not used, default is 16 hours.
; ; Setting it to 0 disables caching
; ITEM_TTL = 16h
[session] [session]
; ; Either "memory", "file", or "redis", default is "memory" ; ; Either "memory", "file", or "redis", default is "memory"
PROVIDER = redis ; PROVIDER = memory
; Provider config options ; ; Provider config options
; redis: network=tcp,addr=:6379,password=macaron,db=0,pool_size=100,idle_timeout=180 ; ; memory: not have any config yet
PROVIDER_CONFIG = "network=tcp,addr=gitea-redis:6379,db=1,pool_size=100,idle_timeout=180" ; ; file: session file path, e.g. `data/sessions`
; ; redis: network=tcp,addr=:6379,password=macaron,db=0,pool_size=100,idle_timeout=180
; ; mysql: go-sql-driver/mysql dsn config string, e.g. `root:password@/session_table`
; PROVIDER_CONFIG = data/sessions
; ; Session cookie name
COOKIE_NAME = i_like_gitea
; ; If you use session in https only, default is false ; ; If you use session in https only, default is false
COOKIE_SECURE = true COOKIE_SECURE = true
; SameSite settings. Either "none", "lax", or "strict" ; ; Enable set cookie, default is true
SAME_SITE = strict ENABLE_SET_COOKIE = true
; ; Session GC time interval in seconds, default is 86400 (1 day)
[migrations] ; GC_INTERVAL_TIME = 86400
ALLOWED_DOMAINS = github.com ; ; Session life time in seconds, default is 86400 (1 day)
ALLOW_LOCALNETWORKS = false SESSION_LIFE_TIME = 2592000
; [picture]
; AVATAR_UPLOAD_PATH = data/avatars
; ; Chinese users can choose "duoshuo"
; ; or a custom avatar source, like: http://cn.gravatar.com/avatar/
; GRAVATAR_SOURCE = gravatar
; ; This value will be forced to be true in offline mode.
; DISABLE_GRAVATAR = false
; ; Federated avatar lookup uses DNS to discover avatar associated
; ; with emails, see https://www.libravatar.org
; ; This value will be forced to be false in offline mode or Gravatar is disabled.
; ENABLE_FEDERATED_AVATAR = false
[attachment] [attachment]
; ; Whether attachments are enabled. Defaults to `true` ; ; Whether attachments are enabled. Defaults to `true`
ENABLE = true ENABLE = true
; ; Path for attachments. Defaults to `data/attachments`
PATH = data/attachments
; ; One or more allowed types, e.g. image/jpeg|image/png ; ; 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 ALLOWED_TYPES = image/jpeg|image/png|application/zip|application/gzip|application/pdf|text/csv
; ; Max size of each file. Defaults to 32MB ; ; Max size of each file. Defaults to 32MB
MAX_SIZE = 200 ; MAX_SIZE = 4
; ; Max number of files per upload. Defaults to 10 ; ; Max number of files per upload. Defaults to 10
MAX_FILES = 10 ; MAX_FILES = 5
[log] ; [time]
; Either "console", "file", "conn", "smtp" or "database", default is "console" ; ; Specifies the format for fully outputted dates. Defaults to RFC1123
; Use comma to separate multiple modes, e.g. "console, file" ; ; Special supported values are ANSIC, UnixDate, RubyDate, RFC822, RFC822Z, RFC850, RFC1123, RFC1123Z, RFC3339, RFC3339Nano, Kitchen, Stamp, StampMilli, StampMicro and StampNano
MODE = console ; ; For more information about the format see http://golang.org/pkg/time/#pkg-constants
; Buffer length of the channel, keep it as it is if you don't know what it is. ; FORMAT =
BUFFER_LEN = 10000
; Either "Trace", "Debug", "Info", "Warn", "Error", "Critical", default is "Trace" ; [log]
LEVEL = Warn ; ROOT_PATH =
REDIRECT_MACARON_LOG = true ; ; Either "console", "file", "conn", "smtp" or "database", default is "console"
ROUTER_LOG_LEVEL = Critical ; ; Use comma to separate multiple modes, e.g. "console, file"
logger.access.MODE=, ; MODE = console
logger.xorm.MODE=, ; ; Buffer length of 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 = Info
; ; For "console" mode only
; [log.console]
; LEVEL =
; ; For "file" mode only
; [log.file]
; LEVEL =
; ; This enables automated log rotate(switch of following options), default is true
; LOG_ROTATE = true
; ; Max line number of single file, default is 1000000
; MAX_LINES = 1000000
; ; Max size shift of single file, default is 28 means 1 << 28, 256MB
; MAX_SIZE_SHIFT = 28
; ; Segment log daily, default is true
; DAILY_ROTATE = true
; ; Expired days of log file(delete after max days), default is 7
; MAX_DAYS = 7
; ; For "conn" mode only
; [log.conn]
; LEVEL =
; ; Reconnect host for every single message, default is false
; RECONNECT_ON_MSG = false
; ; Try to reconnect when connection is lost, default is false
; RECONNECT = false
; ; Either "tcp", "unix" or "udp", default is "tcp"
; PROTOCOL = tcp
; ; Host address
; ADDR =
; ; For "smtp" mode only
; [log.smtp]
; LEVEL =
; ; Name displayed in mail title, default is "Diagnostic message from server"
; SUBJECT = Diagnostic message from server
; ; Mail server
; HOST =
; ; Mailer user name and password
; USER =
; PASSWD =
; ; Receivers, can be one or more, e.g. 1@example.com,2@example.com
; RECEIVERS =
; ; For "database" mode only
; [log.database]
; LEVEL =
; ; Either "mysql" or "postgres"
; DRIVER =
; ; Based on xorm, e.g.: root:root@localhost/gitea?charset=utf8
; CONN =
[cron] [cron]
; Enable running cron tasks periodically. ; Enable running cron tasks periodically.
@ -237,34 +345,107 @@ ENABLED = true
; ; Run cron tasks when Gitea starts. ; ; Run cron tasks when Gitea starts.
RUN_AT_START = false 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 ; ; Update mirrors
[cron.update_mirrors] [cron.update_mirrors]
SCHEDULE = @every 3h SCHEDULE = @every 3h
; ; Repository health check
; [cron.repo_health_check]
; SCHEDULE = @every 24h
; TIMEOUT = 60s
; ; Arguments for command 'git fsck', e.g. "--unreachable --tags"
; ; see more on http://git-scm.com/docs/git-fsck/1.7.5
; ARGS =
; Repository health check ; ; Check repository statistics
[cron.repo_health_check] ; [cron.check_repo_stats]
SCHEDULE = @midnight ; RUN_AT_START = true
TIMEOUT = 60s ; SCHEDULE = @every 24h
; Arguments for command 'git fsck', e.g. "--unreachable --tags"
; see more on http://git-scm.com/docs/git-fsck
ARGS =
; Check repository statistics ; ; Clean up old repository archives
[cron.check_repo_stats] ; [cron.archive_cleanup]
RUN_AT_START = true ; ; Whether to enable the job
SCHEDULE = @midnight ; ENABLED = true
; ; Whether to always run at least once at start up time (if ENABLED)
; RUN_AT_START = true
; ; Time interval for job to run
; SCHEDULE = @every 24h
; ; Archives created more than OLDER_THAN ago are subject to deletion
; OLDER_THAN = 24h
; ; Synchronize external user data (only LDAP user synchronization is supported)
; [cron.sync_external_users]
; ; Synchronize external user data when starting server (default false)
; RUN_AT_START = false
; ; Interval as a duration between each synchronization (default every 24h)
; SCHEDULE = @every 24h
; ; Create new users, update existing user data and disable users that are not in external source anymore (default)
; ; or only create new users if UPDATE_EXISTING is set to false
; UPDATE_EXISTING = true
; [git]
; ; Disables highlight of added and removed changes
; DISABLE_DIFF_HIGHLIGHT = false
; ; Max number of lines allowed of a single file in diff view
; MAX_GIT_DIFF_LINES = 1000
; ; Max number of characters of a line allowed in diff view
; MAX_GIT_DIFF_LINE_CHARACTERS = 5000
; ; Max number of files shown in diff view
; MAX_GIT_DIFF_FILES = 100
; ; Arguments for command 'git gc', e.g. "--aggressive --auto"
; ; see more on http://git-scm.com/docs/git-gc/1.7.5
; GC_ARGS =
; ; Operation timeout in seconds
[git.timeout]
MIGRATE = 600
MIRROR = 300
CLONE = 300
PULL = 300
GC = 60
; [mirror]
; ; Default interval as a duration between each check
; DEFAULT_INTERVAL = 8h
; ; Min interval as a duration must be > 1m
; MIN_INTERVAL = 10m
[api] [api]
; Max number of items will response in a page ; Max number of items will response in a page
MAX_RESPONSE_ITEMS = 100 MAX_RESPONSE_ITEMS = 100
; [i18n]
; LANGS = en-US,zh-CN,zh-HK,zh-TW,de-DE,fr-FR,nl-NL,lv-LV,ru-RU,ja-JP,es-ES,pt-BR,pl-PL,bg-BG,it-IT,fi-FI,tr-TR,cs-CZ,sr-SP,sv-SE,ko-KR
; NAMES = English,简体中文,繁體中文(香港),繁體中文(台灣),Deutsch,français,Nederlands,latviešu,русский,日本語,español,português do Brasil,polski,български,italiano,suomi,Türkçe,čeština,српски,svenska,한국어
; ; Used for datetimepicker
; [i18n.datelang]
; en-US = en
; zh-CN = zh
; zh-HK = zh-TW
; zh-TW = zh-TW
; de-DE = de
; fr-FR = fr
; nl-NL = nl
; lv-LV = lv
; ru-RU = ru
; ja-JP = ja
; es-ES = es
; pt-BR = pt-BR
; pl-PL = pl
; bg-BG = bg
; it-IT = it
; fi-FI = fi
; tr-TR = tr
; cs-CZ = cs-CZ
; sr-SP = sr
; sv-SE = sv
; ko-KR = ko
; ; Extension mapping to highlight class
; ; e.g. .toml=ini
; [highlight.mapping]
[other] [other]
SHOW_FOOTER_BRANDING = false SHOW_FOOTER_BRANDING = false
; Show version information about Gitea and Go in the footer ; Show version information about Gitea and Go in the footer
@ -272,42 +453,16 @@ SHOW_FOOTER_VERSION = true
; Show time of template execution in the footer ; Show time of template execution in the footer
SHOW_FOOTER_TEMPLATE_LOAD_TIME = false SHOW_FOOTER_TEMPLATE_LOAD_TIME = false
; [markup.asciidoc]
; ENABLED = false
; ; List of file extensions that should be rendered by an external command
; FILE_EXTENSIONS = .adoc,.asciidoc
; ; External command to render all matching extensions
; RENDER_COMMAND = "asciidoc --out-file=- -"
; ; Input is not a standard input but a file
; IS_INPUT_FILE = false
[openid] [openid]
ENABLE_OPENID_SIGNIN = true ENABLE_OPENID_SIGNIN = true
ENABLE_OPENID_SIGNUP = false ENABLE_OPENID_SIGNUP = true
[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

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,21 +1,14 @@
# https://github.com/go-gitea/gitea/releases # https://github.com/go-gitea/gitea/releases
data "docker_registry_image" "gitea" { data "docker_registry_image" "gitea" {
name = "gitea/gitea:1.21" name = "gitea/gitea:1.4"
}
data "docker_registry_image" "redis" {
name = "redis:alpine"
} }
data "template_file" "gitea-config-file" { data "template_file" "gitea-config-file" {
template = file("${path.module}/conf/conf.ini.tpl") template = "${file("${path.module}/conf/conf.ini.tpl")}"
vars = { vars {
secret_key = var.secret-key secret_key = "${var.secret-key}"
internal_token = var.internal-token internal_token = "${var.internal-token}"
smtp_password = var.smtp-password smtp_password = "${var.smtp-password}"
lfs-jwt-secret = var.lfs-jwt-secret
mysql-password = var.mysql-password
oauth2-jwt-secret = var.oauth2-jwt-secret
} }
} }

View File

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

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,23 +0,0 @@
resource "docker_container" "redis" {
name = "gitea-redis"
image = docker_image.redis.image_id
volumes {
host_path = "/mnt/xwing/cache/gitea"
container_path = "/data"
}
memory = 64
restart = "always"
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
}

View File

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

View File

@ -1,4 +1,3 @@
resource "docker_volume" "gitea_volume" { resource "docker_volume" "gitea_volume" {
name = "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"
# }
# }
# }

153
main.tf
View File

@ -1,112 +1,89 @@
module "cloudflare" { module "cloudflare" {
source = "./cloudflare" source = "cloudflare"
domain = "bb8.fun" domain = "bb8.fun"
zone_id = lookup(data.cloudflare_zones.bb8.zones[0], "id") ips = "${var.ips}"
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" { module "docker" {
source = "./docker" source = "docker"
web_username = data.pass_password.web_username.password web_username = "${var.web_username}"
web_password = data.pass_password.web_password.password web_password = "${var.web_password}"
cloudflare_key = data.pass_password.cloudflare_key.password mysql_root_password = "${var.mysql_root_password}"
cloudflare_key = "${var.cloudflare_key}"
cloudflare_email = "bb8@captnemo.in" cloudflare_email = "bb8@captnemo.in"
wiki_session_secret = data.pass_password.wiki_session_secret.password wiki_session_secret = "${var.wiki_session_secret}"
ips = var.ips ips = "${var.ips}"
domain = "bb8.fun" 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
username-1 = "vikalp"
username-2 = "rishav"
password-1 = data.pass_password.timemachine-password-1.password
password-2 = data.pass_password.timemachine-password-2.password
}
module "gitea" { module "gitea" {
source = "./gitea" source = "gitea"
domain = "git.captnemo.in" domain = "git.captnemo.in"
traefik-labels = var.traefik-common-labels traefik-labels = "${var.traefik-common-labels}"
ips = var.ips ips = "${var.ips}"
secret-key = data.pass_password.gitea-secret-key.password secret-key = "${var.gitea-secret-key}"
internal-token = data.pass_password.gitea-internal-token.password internal-token = "${var.gitea-internal-token}"
smtp-password = data.pass_password.gitea-smtp-password.password smtp-password = "${var.gitea-smtp-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
} }
module "radicale" { module "radicale" {
source = "./radicale" source = "radicale"
domain = "radicale.bb8.fun" 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 "heimdall" {
source = "heimdall"
domain = "bb8.fun"
traefik-labels = "${var.traefik-common-labels}"
auth-header = "${module.docker.auth-header}"
} }
module "media" { module "media" {
source = "./media" source = "media"
domain = "bb8.fun" domain = "bb8.fun"
traefik-labels = var.traefik-common-labels links-emby = "${module.docker.names-emby}"
ips = var.ips links-transmission = "${module.docker.names-transmission}"
# ToDO: Change this to lookup links-mariadb = "${module.docker.names-mariadb}"
traefik-network-id = "ffc1e366849e" traefik-labels = "${var.traefik-common-labels}"
lastfm_api_key = data.pass_password.navidrome-lastfm-api-key.password airsonic-smtp-password = "${var.airsonic-smtp-password}"
lastfm_secret = data.pass_password.navidrome-lastfm-secret.password airsonic-db-password = "${var.mysql_airsonic_password}"
spotify_id = data.pass_password.navidrome-spotify-id.password
spotify_secret = data.pass_password.navidrome-spotify-secret.password
} }
module "monitoring" { module "monitoring" {
source = "./monitoring" source = "monitoring"
gf-security-admin-password = data.pass_password.gf-security-admin-password.password gf-security-admin-password = "${var.gf-security-admin-password}"
domain = "bb8.fun" domain = "bb8.fun"
transmission = module.media.names-transmission transmission = "${module.docker.names-transmission}"
traefik-labels = var.traefik-common-labels traefik-labels = "${var.traefik-common-labels}"
ips = var.ips ips = "${var.ips}"
links-traefik = module.docker.names-traefik links-traefik = "${module.docker.names-traefik}"
traefik-network-id = module.docker.traefik-network-id
} }
module "digitalocean" { module "digitalocean" {
source = "./digitalocean" source = "digitalocean"
} }
module "home-assistant" {
source = "./home-assistant"
}
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,76 @@
# module "airsonic" { resource "docker_container" "airsonic" {
# source = "../modules/container" name = "airsonic"
# image = "linuxserver/airsonic:latest" image = "${docker_image.airsonic.latest}"
# name = "airsonic" restart = "unless-stopped"
# resource { destroy_grace_seconds = 30
# memory = "1024" must_run = true
# memory_swap = "1024"
# } # Unfortunately, the --device flag is not yet supported
# web { # in docker/terraform:
# port = 4040 # https://github.com/terraform-providers/terraform-provider-docker/issues/30
# host = "airsonic.bb8.fun"
# expose = true upload {
# } content = "${data.template_file.airsonic-properties-file.rendered}"
# networks = "${list(docker_network.media.id, data.docker_network.bridge.id)}" file = "/usr/lib/jvm/java-1.8-openjdk/jre/lib/airsonic.properties"
# env = [ }
# "PUID=1004",
# "PGID=1003", # This lets the Jukebox use ALSA
# "TZ=Asia/Kolkata", upload {
# "JAVA_OPTS=-Xmx512m -Dserver.use-forward-headers=true -Dserver.context-path=/", content = "${file("${path.module}/conf/airsonic.sound.properties")}"
# ] file = "/usr/lib/jvm/java-1.8-openjdk/jre/lib/sound.properties"
# devices = [{ }
# host_path = "/dev/snd"
# container_path = "/dev/snd" volumes {
# }] host_path = "/mnt/xwing/config/airsonic/data"
# # files = [ container_path = "/config"
# # "/usr/lib/jvm/java-1.8-openjdk/jre/lib/airsonic.properties", }
# # "/usr/lib/jvm/java-1.8-openjdk/jre/lib/sound.properties",
# # ] volumes {
# # contents = [ host_path = "/mnt/xwing/media/Music"
# # "${data.template_file.airsonic-properties-file.rendered}", container_path = "/music"
# # "${file("${path.module}/conf/airsonic.sound.properties")}", }
# # ]
# volumes = [ volumes {
# { host_path = "/mnt/xwing/config/airsonic/playlists"
# host_path = "/mnt/xwing/config/airsonic2" container_path = "/playlists"
# container_path = "/config" }
# },
# { volumes {
# host_path = "/mnt/xwing/media/Music" host_path = "/mnt/xwing/config/airsonic/podcasts"
# container_path = "/music" container_path = "/podcasts"
# }, }
# {
# host_path = "/mnt/xwing/config/airsonic/playlists" labels {
# container_path = "/playlists" "traefik.enable" = "true"
# }, "traefik.port" = "4040"
# { "traefik.frontend.rule" = "Host:airsonic.in.${var.domain},airsonic.${var.domain}"
# host_path = "/mnt/xwing/config/airsonic/podcasts" "traefik.frontend.passHostHeader" = "true"
# container_path = "/podcasts" }
# },
# { # lounge:tatooine
# host_path = "/mnt/xwing/config/airsonic/jre" env = [
# container_path = "/usr/lib/jvm/java-1.8-openjdk/jre/lib/" "PUID=1004",
# }, "PGID=1003",
# ] "TZ=Asia/Kolkata",
# } ]
# data "template_file" "airsonic-properties-file" {
# template = "${file("${path.module}/conf/airsonic.properties.tpl")}" links = ["${var.links-mariadb}"]
# vars { }
# smtp-password = "${var.airsonic-smtp-password}"
# # db-password = "${var.airsonic-db-password}" 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 SmtpUser=airsonic@captnemo.in
SmtpFrom=airsonic@captnemo.in SmtpFrom=airsonic@captnemo.in
SmtpPassword=${smtp-password} SmtpPassword=${smtp-password}
DatabaseConfigType=embed
DatabaseConfigEmbedDriver=org.hsqldb.jdbcDriver
DatabaseConfigEmbedUrl=jdbc:mysql://mariadb:3306/airsonic
DatabaseConfigEmbedUsername=airsonic
DatabaseConfigEmbedPassword=${db-password}

34
media/daapd.tf Normal file
View File

@ -0,0 +1,34 @@
data "docker_registry_image" "daapd" {
name = "linuxserver/daapd:latest"
}
resource "docker_image" "daapd" {
name = "${data.docker_registry_image.daapd.name}"
pull_triggers = ["${data.docker_registry_image.daapd.sha256_digest}"]
}
resource "docker_container" "daapd" {
name = "daapd"
image = "${docker_image.daapd.latest}"
restart = "unless-stopped"
destroy_grace_seconds = 10
must_run = true
network_mode = "host"
volumes {
host_path = "/mnt/xwing/config/daapd"
container_path = "/config"
}
volumes {
host_path = "/mnt/xwing/media/Music"
container_path = "/music"
}
env = [
"PUID=1004",
"PGID=1003",
"TZ=Asia/Kolkata",
]
}

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" { data "docker_registry_image" "jackett" {
name = "jackett" name = "linuxserver/jackett:latest"
source = "../modules/container" }
image = "linuxserver/jackett:latest"
# TODO FIXME
# networks = [data.docker_network.bridge.id]
web = { resource "docker_image" "jackett" {
expose = true name = "${data.docker_registry_image.jackett.name}"
port = 9117 pull_triggers = ["${data.docker_registry_image.jackett.sha256_digest}"]
host = "jackett.${var.domain}" }
}
volumes = [ resource docker_container "jackett" {
{ name = "jackett"
host_path = "/mnt/xwing/config/jackett" image = "${docker_image.jackett.latest}"
container_path = "/config"
},
]
resource = { labels = "${merge(
memory = "256" var.traefik-labels, map(
memory_swap = "512" "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 = [ env = [
@ -28,5 +31,6 @@ module "jackett" {
"PGID=1003", "PGID=1003",
"TZ=Asia/Kolkata", "TZ=Asia/Kolkata",
] ]
}
# links = ["${var.links-emby}"]
}

View File

@ -1,58 +0,0 @@
data "docker_registry_image" "lidarr" {
name = "linuxserver/lidarr:latest"
}
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}"
})
}
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
}
}
memory = 512
restart = "unless-stopped"
destroy_grace_seconds = 10
must_run = true
volumes {
host_path = "/mnt/xwing/config/lidarr"
container_path = "/config"
}
volumes {
host_path = "/mnt/xwing/media/DL"
container_path = "/downloads"
}
volumes {
host_path = "/mnt/xwing/media/Music"
container_path = "/music"
}
env = [
"PUID=1004",
"PGID=1003",
"TZ=Asia/Kolkata",
]
networks = [docker_network.media.id, var.traefik-network-id]
}

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"
}
}

38
media/ombi.tf Normal file
View File

@ -0,0 +1,38 @@
data "docker_registry_image" "ombi" {
name = "lsiodev/ombi-preview"
}
resource "docker_image" "ombi" {
name = "${data.docker_registry_image.ombi.name}"
pull_triggers = ["${data.docker_registry_image.ombi.sha256_digest}"]
}
resource docker_container "ombi" {
name = "ombi"
image = "${docker_image.ombi.latest}"
labels = "${merge(
var.traefik-labels, map(
"traefik.port", 3579,
"traefik.frontend.rule","Host:ombi.${var.domain}"
))}"
restart = "unless-stopped"
destroy_grace_seconds = 10
must_run = true
volumes {
host_path = "/mnt/xwing/config/ombi"
container_path = "/config"
}
env = [
"TZ=Asia/Kolkata",
]
links = [
"${var.links-emby}",
"${docker_container.sonarr.name}",
"${docker_container.radarr.name}",
]
}

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]
}

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