Compare commits

...

121 Commits

Author SHA1 Message Date
Nemo bd95967113 upgrade miniflux and gitea 2023-11-28 10:35:39 +05:30
Nemo 3f3f0fd55c re-enable GPU on Emby 2023-10-26 13:10:47 +05:30
Nemo 1b1bbcabbc drop act-exporter
I archived the repo, and no longer maintain it. ACT changed
their portal too much for this to keep working. Further,
the ACT app/portal now provide detailed stats on internet
usage, so this is not that helpful any more.
2023-10-26 13:09:32 +05:30
Nemo dfd0f94662 fix resource limits for grafana,cadvisor 2023-10-26 13:08:14 +05:30
Nemo 09c1094fc5 upgrade mastodon 2023-10-26 13:07:56 +05:30
Nemo 29368acfed upgrade miniflux 2023-10-26 13:07:45 +05:30
Nemo e18d8b11b1 Adds home-assistant
Trying to run https://hackaday.com/2021/07/24/esp8266-adds-wifi-logging-to-ikeas-air-quality-sensor/
2023-08-03 17:00:18 +05:30
Nemo 1feaf2e4f6 Migrate Emby to the SSD, and configure backups
Note that creating the directory alone doesn't do much.
You still have to configure backups and schedule them in the UI.
2023-07-27 13:36:00 +05:30
Nemo 2c52cd0cb7 gitea/miniflux upgrades 2023-07-26 09:40:02 +05:30
Nemo b83dd37365 [radicale] switch to ssd 2023-07-10 19:59:55 +05:30
Nemo af2be53caa [navidrome] Move to ssd 2023-07-10 17:12:03 +05:30
Nemo 9e8c5710f2 upgrade mastodon and use persistent redis 2023-07-10 17:01:50 +05:30
Nemo e4858d5d05 move sonarr/radarr to ssd 2023-07-10 17:01:30 +05:30
Nemo d59512c625 HSTS Preload on tatooine.club 2023-06-22 14:24:26 +05:30
Nemo 4a4504447f upgrade miniflux 2023-06-22 13:15:17 +05:30
Nemo 9b316b036b upgrade mastodon 2023-06-22 13:15:10 +05:30
Nemo f9b52957a8 fix resolver for dns/acme 2023-06-01 14:01:12 +05:30
Nemo 9b79cab3af gitea upgrade and fixes
fixes the svg favicons, but these are not nice
2023-06-01 14:01:06 +05:30
Nemo 5bd44d411f mastodon image conflict fixes 2023-06-01 14:00:08 +05:30
Nemo 406f4557fe fix+upgrade miniflux resource limits 2023-06-01 13:59:55 +05:30
Nemo 938ed017c9 Upgrade mastodon 2023-03-11 17:19:01 +05:30
Nemo 4f2a5b2cb4 Additional Mastodon secrets 2022-12-26 13:19:00 +05:30
Nemo ecaacaf3a5 [transmission] Upgrade configuration 2022-12-26 12:51:44 +05:30
Nemo af20a4efb9 [traefik] Upgrade 1.17 conf for tatooine.club 2022-12-26 12:51:30 +05:30
Nemo 18f32691f6 [media] Upgrade subnet size 2022-12-26 12:50:54 +05:30
Nemo eb1c40df6e [kaarana] Unused, but upgraded 2022-12-26 12:50:43 +05:30
Nemo 4b6b07c09a [db] Increase connections for mastodon 2022-12-26 12:50:31 +05:30
Nemo 48b93bf25d GPU and provider upgrades.
Applied to jupyter container
2022-12-26 12:49:52 +05:30
Nemo 8a894175a9 [miniflux] Upgrade to 2.0.39 2022-12-26 12:49:23 +05:30
Nemo 30fd75ae52 [main] Mastodon added 2022-12-26 12:49:13 +05:30
Nemo 9f6048a971 [gitea] Upgrades to 1.17 2022-12-26 12:48:59 +05:30
Nemo 442ec2d5d3 [traefik] New tatooine.club keys
Had to disable redirect
2022-12-26 12:48:34 +05:30
Nemo 9f04ebe4c4 [rss-bridge] Switch to upstream
Most of my changes are merged: captnemo.in/rss/
So I can switch to tracking upstream instead
2022-12-26 12:48:03 +05:30
Nemo 587b6258bb Mastodon: Initial Configuration
This is missing some secrets, will commit those later
2022-12-26 12:47:48 +05:30
Nemo da4fc888ef [WIP] Traefik v2 migration 2022-12-26 12:46:31 +05:30
Nemo 10ba57590b Switch from latest -> image_id
former is deprecated
2022-12-26 12:46:09 +05:30
Nemo 8a0ead5bb0 [postgres] Increase memory for mastodon 2022-12-26 12:44:55 +05:30
Nemo 36996a0ace Increase network size for pg to add mastodon containers 2022-12-26 12:44:03 +05:30
Nemo 24079f41a2 Upgrade Terraform version 2022-12-26 12:43:47 +05:30
Nemo 51dd19cdc8 add prowlarr 2022-02-02 19:06:13 +05:30
Nemo 1235775ed0 upgrade gitea to 1.16 2022-02-02 19:03:28 +05:30
Nemo ffa2517903 addded kavita then removed it 2022-01-08 22:19:47 +05:30
Nemo ba763d585c minor fixes and upgrades 2022-01-08 22:19:38 +05:30
Nemo f6b1954e8f no more firefox sync, Mozilla makes this too hard 2021-10-16 11:41:30 +05:30
Nemo 137eb3469f
Terraform Upgrade to 1.x (#3)
Co-authored-by: Hashfyre <joy.bhattacherjee@gmail.com>
2021-10-15 12:54:13 +00:00
Nemo 8d7875d174 Fix radicale 2021-04-14 12:30:35 +05:30
Nemo 9273447567 increase memory for radicale 2021-04-14 12:08:31 +05:30
Nemo eae805e596 Update gitea, improve config 2021-04-14 12:08:21 +05:30
Nemo c6ebee47d7 Replace gonic with navidrome 2021-02-16 19:58:53 +05:30
Nemo 1a0021fb31 update miniflux 2021-02-16 19:58:41 +05:30
Nemo 42a264c7bd Disable SSH, upgrade gitea 2021-02-02 18:31:56 +05:30
Nemo 09baca2819 remove unused code 2021-02-02 15:14:48 +05:30
Nemo d25573f4b0 upgrade miniflux 2021-02-02 15:14:37 +05:30
Nemo 6cb2ffa736 Security note about docker socket mount 2021-02-02 14:07:15 +05:30
Nemo d90a67539f Remove heimdall 2021-02-02 13:58:10 +05:30
Nemo a532831de9 remove abstruse 2021-02-02 13:52:51 +05:30
Nemo 2d2348f34f [ubooquity] Enable autoscan 2021-01-27 13:17:53 +05:30
Nemo 114bb27349 Adds requestrr 2021-01-27 13:01:44 +05:30
Nemo add21ccdac Adds klaxon 2021-01-27 12:58:32 +05:30
Nemo c3584a8f56 Removes unused code 2021-01-27 12:55:08 +05:30
Nemo 20cd656e04 Removes mongodb, upgrades wiki 2021-01-08 00:23:33 +05:30
Nemo 373793fcb5 Setup one for audiobooks 2020-10-11 18:29:56 +05:30
Nemo 4922bd098f got gonic working 2020-10-10 19:02:50 +05:30
Nemo 735279b0c1 Cleanup and comment unused stuff 2020-07-29 22:49:35 +05:30
Nemo 86db1b2da9 upgrades+gonic 2019-12-31 21:53:39 +05:30
Nemo 1a234f5025 only run webserver for elibsrv 2019-11-04 01:51:56 +05:30
Nemo f02ee532ad mount books as read-only 2019-11-04 01:40:18 +05:30
Nemo 557a0af80d Merge branch 'master' into kaarana-wordpress 2019-10-09 04:58:13 +05:30
Nemo 2b617967a3 upgrade elibsrv 2019-10-09 04:50:09 +05:30
Nemo cce99c0b6a WIP ingress configuration
- Traefik is advertising http/2 along with TLS
  it then forwards the unencrypted h2 to the php server
  which is then giving up.

(╯°□°)╯︵ ┻━┻
2019-09-21 07:55:55 +05:30
Nemo 42ab949caf Fix wordpress port 2019-09-21 06:02:16 +05:30
Nemo d4370f2b56 kaarana.org wordpress website 2019-09-21 04:59:39 +05:30
Nemo 0633f6113f The SSH and Web servers are on different IP addresses now 2019-09-14 18:32:09 +05:30
Nemo 4336814bac Fix audioserve 2019-09-14 17:32:17 +05:30
Nemo 975c48094f Upgrade redis 2019-08-12 00:27:44 +05:30
Nemo 8900b2d2be remove lychee and stringer 2019-08-12 00:21:47 +05:30
Nemo 2b2b68f722 General Updates 2019-08-11 21:40:29 +05:30
Nemo da53ac8f1a Increase memory for radicale 2019-06-28 23:52:44 +05:30
Nemo 125f4cecaf Adds stringer
- Doesn't work yet, have create an issue
2019-06-23 22:37:56 +05:30
Nemo 273b75841c Increase resources for rssbridge 2019-06-21 01:44:11 +05:30
Nemo c890430913 adds a subject prefix for gitea mails 2019-06-02 15:43:50 +05:30
Nemo 1617061f51 [gitea] New release forces oauth2 on everyone 2019-06-02 15:41:06 +05:30
Nemo 63facbde70 Remove custom dns support 2019-06-02 14:51:33 +05:30
Nemo c5677d0fa4 docker improvements got merged 2019-06-01 22:43:00 +05:30
Nemo 77afa90a64 Fix whitelist path 2019-05-28 17:08:50 +05:30
Nemo bd27db6aa6 Switch to official PHP base image 2019-05-28 16:05:16 +05:30
Nemo ae073752a1 Fix ACT Exporter 2019-05-19 12:52:02 +05:30
Nemo b862c78ec9 General Updates 2019-05-19 12:51:53 +05:30
Nemo c066e62ee0 Fix radicale 2019-05-16 16:07:01 +05:30
Nemo c152ec65df Adds elibsrv Docker Container 2019-05-12 09:01:46 +05:30
Nemo 4c55f5dd0f Updates gitea config for 1.8 2019-05-12 09:01:35 +05:30
Nemo d748e65a37 Block robots from scraping git.captnemo.in
- Too many requests
2019-04-27 16:33:52 +05:30
Nemo 3bc9e40b61 Get opml back 2019-04-27 16:24:48 +05:30
Nemo 1bc37d72a6 Force run stuff 2019-04-27 00:28:11 +05:30
Nemo 37bb59eda3 Run a jupyter notebook 2019-04-26 03:16:37 +05:30
Nemo 07d44ca39a Comment out unused kubernetes stuff 2019-04-26 03:16:25 +05:30
Nemo c9b9205496 Switch to stable release of nextcloud 2019-04-21 17:45:28 +05:30
Nemo 071a16dc94 Improve NextCloud Networking 2019-04-16 00:38:40 +05:30
Nemo d9ef272286 Fix Firefox Sync 2019-04-14 00:11:55 +05:30
Nemo 114487fc1e Fix pass provider issues 2019-04-13 03:01:36 +05:30
Nemo c2e029fb4f Adds audioserve 2019-04-02 02:55:26 +05:30
Nemo 0ce0753d5f turn off dnscrypt-proxy, client now runs on the Router 2019-03-31 17:09:43 +05:30
Nemo ff3b56231b fix rss-bridge 2019-03-26 12:48:43 +05:30
Nemo ace703fc1f Switch to pass-provider for secrets 2019-03-25 21:04:47 +05:30
Nemo d7a6d06ec2 switch to master for rss-bridge 2019-03-18 03:30:32 +05:30
Nemo 6362702c51 Fix Emby DNS to dnscrypt 2019-03-17 02:15:02 +05:30
Nemo 4fe34b183a Pihole and Dnscrypt Proxy Setup is done 2019-03-13 22:55:06 +05:30
Nemo 16a5a26123 Switch to aliases for container<>networking 2019-03-09 13:58:57 +05:30
Nemo 2b53a6a512 Add default bridge network 2019-03-09 13:54:01 +05:30
Nemo 6ec37264dc nextcloud and other minor changes 2019-03-09 13:22:54 +05:30
Nemo 995fb96611 Fixes Airsonic (mostly) 2019-02-20 00:52:09 +05:30
Nemo 435e166cd9 Adds jellyfin 🐟 2019-02-16 20:32:16 +05:30
Nemo ae985e01a7 Adds dnscrypt-proxy and pihole
pihole commented for now
2019-02-16 15:42:07 +05:30
Nemo e4b3620de5 Merge branch 'kubernetes' 2019-02-16 13:52:48 +05:30
Nemo 83eb97c8db Create etcd dns entry 2019-02-13 20:37:38 +05:30
Nemo 40b967edce Migrate to kayak 2019-02-10 23:14:21 +05:30
Nemo f85692da9e Switch to a remote state 2019-02-10 23:14:10 +05:30
Nemo 97300459fd General Updates 2019-02-03 18:39:10 +05:30
Nemo 80ce34d52f Bring up a sample pod 2019-02-02 23:21:49 +05:30
Nemo 86f2edc112 Get cluster up and running 2019-02-02 22:55:55 +05:30
Nemo 53f3c87600 some media updates 2019-01-29 00:50:00 +05:30
151 changed files with 2909 additions and 2328 deletions

4
.gitignore vendored
View File

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

View File

@ -1 +1 @@
0.11.8
1.3.6

18
HACKING.md Normal file
View File

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

View File

@ -11,6 +11,7 @@ Manages the local infrastructure of my home server. I'm also doing blog posts ar
3. [Part 3, Learnings](https://captnemo.in/blog/2017/12/18/home-server-learnings/)
4. [Part 4, Migrating from Google (and more)](https://captnemo.in/blog/2017/12/31/migrating-from-google/)
5. [Part 5, Networking](https://captnemo.in/blog/2018/04/22/home-server-networking/)
6. [Part 6, RAID](https://captnemo.in/blog/2019/02/24/btrfs-raid-device-replacement-story/)
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>
@ -40,9 +41,7 @@ Currently running the following (all links are to the `store.docker.com` links f
| image | tag | module/link |
| -------------------------------- | ---------- | ---------------------------------------------------- |
| bleenco/abstruse | latest | ci |
| captn3m0/opml-gen | latest | https://opml.bb8.fun |
| captn3m0/prometheus-act-exporter | latest | https://git.captnemo.in/nemo/prometheus-act-exporter |
| 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 |
@ -51,19 +50,14 @@ Currently running the following (all links are to the `store.docker.com` links f
| grafana/grafana | latest | monitoring |
| jankysolutions/requestbin | latest | tools |
| linuxserver/airsonic | latest | media |
| linuxserver/heimdall | latest | tools |
| linuxserver/jackett | latest | media |
| linuxserver/lidarr | latest | media |
| linuxserver/lychee | latest | media |
| linuxserver/radarr | latest | media |
| linuxserver/resilio-sync | latest | sync |
| linuxserver/sonarr | latest | media |
| linuxserver/transmission | latest | media |
| linuxserver/ubooquity | latest | media |
| miniflux/miniflux | 2.0.9 | tools |
| monicahq/monicahq | latest | services |
| odarriba/timemachine | latest | tools |
| percona/percona-server-mongodb | 3.4 | database |
| postgres | 10-alpine | database |
| prom/node-exporter | v0.15.2 | monitoring |
| prom/prometheus | latest | monitoring |

View File

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

View File

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

View File

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

7
cloudflare/providers.tf Normal file
View File

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

View File

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

View File

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

View File

@ -1,34 +0,0 @@
resource "docker_container" "mongorocks" {
name = "mongorocks"
image = "${docker_image.percona-mongodb-server.latest}"
restart = "unless-stopped"
destroy_grace_seconds = 30
must_run = true
memory = 256
volumes {
volume_name = "${docker_volume.mongorocks_data_volume.name}"
container_path = "/data/db"
host_path = "${docker_volume.mongorocks_data_volume.mountpoint}"
}
command = [
"--storageEngine=rocksdb",
"--httpinterface",
"--rest",
"--master",
]
networks = ["${docker_network.mongorocks.id}"]
}
resource "docker_image" "percona-mongodb-server" {
name = "${data.docker_registry_image.percona-mongodb-server.name}"
pull_triggers = ["${data.docker_registry_image.percona-mongodb-server.sha256_digest}"]
}
# Database versions shouldn't be upgraded
data "docker_registry_image" "percona-mongodb-server" {
name = "percona/percona-server-mongodb:3.4"
}

View File

@ -1,21 +1,10 @@
resource "docker_network" "mongorocks" {
name = "mongorocks"
driver = "bridge"
internal = false
ipam_config {
subnet = "172.20.0.0/29"
gateway = "172.20.0.1"
}
}
resource "docker_network" "postgres" {
name = "postgres"
driver = "bridge"
internal = true
ipam_config {
subnet = "172.20.0.8/29"
subnet = "172.20.0.8/27"
gateway = "172.20.0.9"
}
}

View File

@ -1,7 +1,4 @@
output "networks-mongorocks" {
value = "${docker_network.mongorocks.name}"
output "postgres-network-id" {
value = docker_network.postgres.name
}
output "postgres-network-id" {
value = "${docker_network.postgres.name}"
}

View File

@ -1,18 +1,26 @@
resource "docker_container" "postgres" {
name = "postgres"
image = "${docker_image.postgres.latest}"
image = docker_image.postgres.image_id
command = [
"postgres",
"-c",
"max_connections=250",
"-c",
"shared_buffers=500MB",
]
volumes {
volume_name = "${docker_volume.postgres_volume.name}"
volume_name = docker_volume.pg_data.name
container_path = "/var/lib/postgresql/data"
host_path = "${docker_volume.postgres_volume.mountpoint}"
read_only = false
}
// This is so that other host-only services can share this
ports {
internal = 5432
external = 5432
ip = "${var.ips["eth0"]}"
ip = var.ips["eth0"]
}
// This is a not-so-great idea
@ -20,10 +28,11 @@ resource "docker_container" "postgres" {
ports {
internal = 5432
external = 5432
ip = "${var.ips["tun0"]}"
ip = var.ips["tun0"]
}
memory = 256
memory = 2048
memory_swap = 2048
restart = "unless-stopped"
destroy_grace_seconds = 10
must_run = true
@ -32,12 +41,12 @@ resource "docker_container" "postgres" {
"POSTGRES_PASSWORD=${var.postgres-root-password}",
]
networks = ["${docker_network.postgres.id}", "${data.docker_network.bridge.id}"]
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}"]
name = data.docker_registry_image.postgres.name
pull_triggers = [data.docker_registry_image.postgres.sha256_digest]
}
data "docker_registry_image" "postgres" {

10
db/providers.tf Normal file
View File

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

View File

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

View File

@ -1,7 +1,3 @@
resource "docker_volume" "postgres_volume" {
name = "postgres_volume"
}
resource "docker_volume" "mongorocks_data_volume" {
name = "mongorocks_data_volume"
resource "docker_volume" "pg_data" {
name = "pg_data"
}

View File

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

View File

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

View File

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

19
digitalocean/providers.tf Normal file
View File

@ -0,0 +1,19 @@
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

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

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

View File

@ -150,36 +150,38 @@
"9df97ced8b4de090c469244230ca64f5164ff37e9fde2314cf8c2e87db6d033b"
}
],
"isFilesProviderEnabled": true,
"isComicsProviderEnabled": true,
"isBooksProviderEnabled": true,
"isUserManagementEnabled": true,
"libraryPortNumber": 2202,
"adminPortNumber": 2203,
"comicWidth": 160,
"comicHeight": 230,
"comicsPaginationNumber": 30,
"bookWidth": 160,
"bookHeight": 230,
"booksPaginationNumber": 30,
"minimizeToTray": false,
"minimizeOnStartup": false,
"autoscanPeriod": 0,
"isRemoteAdminEnabled": true,
"theme": "default",
"isShrinkingCacheEnabled": false,
"shrunkPageWidth": 1536,
"shrunkPageHeight": 2500,
"shrinkingCachePath": "",
"autoScanAtLaunch": false,
"reverseProxyPrefix": "",
"keystorePath": "",
"keystorePassword": "",
"isOpdsProviderEnabled": true,
"folderExclusionPattern": "",
"bypassSingleRootFolder": false,
"enableFolderMetadataDisplay": true,
"bookmarkUsingCookies": false,
"displayTitleInsteadOfFileName": true,
"keepUnreachableSharedFolders": false
"isFilesProviderEnabled" : true,
"isComicsProviderEnabled" : true,
"isBooksProviderEnabled" : true,
"isUserManagementEnabled" : true,
"libraryPortNumber" : 2202,
"adminPortNumber" : 2203,
"comicWidth" : 160,
"comicHeight" : 230,
"comicsPaginationNumber" : 30,
"bookWidth" : 160,
"bookHeight" : 230,
"booksPaginationNumber" : 30,
"minimizeToTray" : false,
"minimizeOnStartup" : false,
"autoscanPeriod" : 1440,
"isRemoteAdminEnabled" : true,
"theme" : "default",
"isShrinkingCacheEnabled" : false,
"shrunkPageWidth" : 1536,
"shrunkPageHeight" : 2500,
"shrinkingCachePath" : "",
"autoScanAtLaunch" : false,
"reverseProxyPrefix" : "",
"keystorePath" : "",
"keystorePassword" : "",
"isOpdsProviderEnabled" : true,
"folderExclusionPattern" : "",
"bypassSingleRootFolder" : false,
"enableFolderMetadataDisplay" : true,
"bookmarkUsingCookies" : false,
"displayTitleInsteadOfFileName" : true,
"keepUnreachableSharedFolders" : false,
"isCalibreLibrary" : false,
"instanceId" : "3a0e4425a8e14c719ca2eb382f85292e"
}

15
docker/conf/wiki.tpl Normal file
View File

@ -0,0 +1,15 @@
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

View File

@ -1,142 +0,0 @@
#######################################################################
# 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 (force disabled)
# ---------------------------------------------------------------------
# git: false
git:
url: https://git.captnemo.in/nemo/wiki
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,13 +1,7 @@
data "docker_registry_image" "traefik" {
# Critical and I like upgrading it
# for updating config for new features
name = "traefik:1.7"
}
data "docker_registry_image" "wikijs" {
name = "requarks/wiki:latest"
}
data "docker_registry_image" "ubooquity" {
name = "linuxserver/ubooquity:latest"
}
@ -15,3 +9,4 @@ data "docker_registry_image" "ubooquity" {
data "docker_registry_image" "lychee" {
name = "linuxserver/lychee:latest"
}

View File

@ -6,22 +6,15 @@ data "docker_registry_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.latest}"
# image = "${docker_image.gotviz.image_id}"
# labels = "${merge(
# local.traefik_common_labels, map(
# "traefik.port", 8080,
# "traefik.frontend.rule","Host:got-relationships.${var.domain}"
# ))}"
# restart = "unless-stopped"
# destroy_grace_seconds = 60
# must_run = true
# }

View File

@ -1,19 +1,14 @@
resource "docker_image" "traefik17" {
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}"]
name = data.docker_registry_image.traefik.name
pull_triggers = [data.docker_registry_image.traefik.sha256_digest]
}
resource "docker_image" "ubooquity" {
name = "${data.docker_registry_image.ubooquity.name}"
pull_triggers = ["${data.docker_registry_image.ubooquity.sha256_digest}"]
name = data.docker_registry_image.ubooquity.name
pull_triggers = [data.docker_registry_image.ubooquity.sha256_digest]
}
resource "docker_image" "lychee" {
name = "${data.docker_registry_image.lychee.name}"
pull_triggers = ["${data.docker_registry_image.lychee.sha256_digest}"]
}
# resource "docker_image" "lychee" {
# name = "${data.docker_registry_image.lychee.name}"
# pull_triggers = ["${data.docker_registry_image.lychee.sha256_digest}"]
# }

View File

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

View File

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

View File

@ -1 +0,0 @@

View File

@ -3,3 +3,4 @@ resource "docker_network" "traefik" {
driver = "bridge"
internal = true
}

View File

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

19
docker/providers.tf Normal file
View File

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

View File

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

View File

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

View File

@ -1 +0,0 @@

View File

@ -1,54 +0,0 @@
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}",
))}"
networks = [
"${var.networks-mongorocks}",
"${docker_network.traefik.id}",
]
env = [
"WIKI_ADMIN_EMAIL=me@captnemo.in",
"SESSION_SECRET=${var.wiki_session_secret}",
]
}

View File

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

45
elibsrv.tf Normal file
View File

@ -0,0 +1,45 @@
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,30 +0,0 @@
module "firefox-sync" {
name = "firefox-sync"
source = "./modules/container"
image = "mozilla/syncserver:latest"
// Default is port 80
web {
expose = true
port = "5000"
host = "firesync.${var.root-domain}"
}
volumes = [{
host_path = "/mnt/xwing/data/firefox-sync"
container_path = "/data"
}]
env = [
"SYNCSERVER_PUBLIC_URL=https://firesync.${var.root-domain}",
"SYNCSERVER_SECRET=${var.syncserver_secret}",
"SYNCSERVER_SQLURI=sqlite:////data/sync.db",
"SYNCSERVER_BATCH_UPLOAD_ENABLED=true",
"SYNCSERVER_FORCE_WSGI_ENVIRON=true",
"PORT=5000",
]
networks = [
"${list(module.docker.traefik-network-id)}",
]
}

View File

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

@ -0,0 +1,56 @@
<?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>

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

@ -0,0 +1,22 @@
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: /

22
gitea/conf/robots.txt Normal file
View File

@ -0,0 +1,22 @@
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,7 +1,6 @@
# https://github.com/go-gitea/gitea/releases
data "docker_registry_image" "gitea" {
# not bleeding, this is hemorrhaging edge
name = "gitea/gitea:1.7"
name = "gitea/gitea:1.21"
}
data "docker_registry_image" "redis" {
@ -9,13 +8,14 @@ data "docker_registry_image" "redis" {
}
data "template_file" "gitea-config-file" {
template = "${file("${path.module}/conf/conf.ini.tpl")}"
template = file("${path.module}/conf/conf.ini.tpl")
vars {
secret_key = "${var.secret-key}"
internal_token = "${var.internal-token}"
smtp_password = "${var.smtp-password}"
lfs-jwt-secret = "${var.lfs-jwt-secret}"
mysql-password = "${var.mysql-password}"
vars = {
secret_key = var.secret-key
internal_token = var.internal-token
smtp_password = var.smtp-password
lfs-jwt-secret = var.lfs-jwt-secret
mysql-password = var.mysql-password
oauth2-jwt-secret = var.oauth2-jwt-secret
}
}

View File

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

View File

@ -1 +0,0 @@

View File

@ -2,3 +2,4 @@ resource "docker_network" "gitea" {
name = "gitea"
driver = "bridge"
}

19
gitea/providers.tf Normal file
View File

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

View File

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

View File

@ -1,17 +1,32 @@
variable "traefik-labels" {
type = "map"
type = map(string)
}
variable "domain" {}
variable "domain" {
}
variable "ips" {
type = "map"
type = map(string)
}
variable "secret-key" {}
variable "internal-token" {}
variable "smtp-password" {}
variable "lfs-jwt-secret" {}
variable "mysql-password" {}
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 "traefik-network-id" {}

View File

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

View File

@ -1,19 +0,0 @@
module "heimdall" {
name = "heimdall"
source = "modules/container"
image = "linuxserver/heimdall:latest"
web {
expose = true
port = 443
protocol = "https"
basicauth = "true"
host = "home.bb8.fun"
}
networks = "${list(module.docker.traefik-network-id)}"
env = [
"TZ=Asia/Kolkata",
]
}

24
home-assistant/main.tf Normal file
View File

@ -0,0 +1,24 @@
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"
},
]
}

16
jupyter.tf Normal file
View File

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

21
kaarana.tf Normal file
View File

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

40
kaarana/database.tf Normal file
View File

@ -0,0 +1,40 @@
// 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"]
}

27
kaarana/images.tf Normal file
View File

@ -0,0 +1,27 @@
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]
}

64
kaarana/traefik.tf Normal file
View File

@ -0,0 +1,64 @@
// 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"
}
}

45
kaarana/traefik.toml Normal file
View File

@ -0,0 +1,45 @@
# 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"
]

12
kaarana/vars.tf Normal file
View File

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

40
kaarana/wordpress.tf Normal file
View File

@ -0,0 +1,40 @@
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"]
}

33
kavita.tf Normal file
View File

@ -0,0 +1,33 @@
# 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",
# ]
# }

41
kayak.tf Normal file
View File

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

40
klaxon.tf Normal file
View File

@ -0,0 +1,40 @@
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"]
}

19
kube-test.tf Normal file
View File

@ -0,0 +1,19 @@
// 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"
# }
# }
# }

View File

@ -1,77 +0,0 @@
module "etcd" {
source = "modules/etcd"
data_dir = "/mnt/disk/etcd"
host_bind_ip = "10.8.0.1"
domain = "etcd.bb8.fun"
pki = {
ca_cert = "${module.bootkube.etcd_ca_cert}"
server_cert = "${module.bootkube.etcd_server_cert}"
server_key = "${module.bootkube.etcd_server_key}"
peer_cert = "${module.bootkube.etcd_peer_cert}"
peer_key = "${module.bootkube.etcd_peer_key}"
}
providers = {
docker = "docker.sydney"
}
depends_on = "${module.bootkube.id}"
}
module "kubelet-master" {
source = "modules/kubelet"
host_ip = "${var.ips["dovpn"]}"
k8s_host = "k8s.${var.root-domain}"
assets = {
kubeconfig = "${module.bootkube.kubeconfig-kubelet}"
ca_cert = "${base64decode(module.bootkube.ca_cert)}"
kubelet_cert = "${base64decode(module.bootkube.kubelet_cert)}"
kubelet_key = "${base64decode(module.bootkube.kubelet_key)}"
}
depends_on = "${module.bootkube-start.image}"
providers = {
docker = "docker.sydney"
}
}
module "bootkube-start" {
source = "modules/bootkube"
mode = "start"
host_ip = "${var.ips["dovpn"]}"
k8s_host = "k8s.${var.root-domain}"
asset-dir = "${path.root}/k8s"
assets = {
kubeconfig = "${module.bootkube.kubeconfig-kubelet}"
ca_cert = "${base64decode(module.bootkube.ca_cert)}"
kubelet_cert = "${base64decode(module.bootkube.kubelet_cert)}"
kubelet_key = "${base64decode(module.bootkube.kubelet_key)}"
kubeconfig-kubelet = "${module.bootkube.kubeconfig-kubelet}"
# etcd_ca_cert = "${module.bootkube.etcd_ca_cert}"
# etcd_client_cert = "${module.bootkube.etcd_client_cert}"
# etcd_client_key = "${module.bootkube.etcd_client_key}"
# etcd_server_cert = "${module.bootkube.etcd_server_cert}"
# etcd_server_key = "${module.bootkube.etcd_server_key}"
# etcd_peer_cert = "${module.bootkube.etcd_peer_cert}"
# etcd_peer_key = "${module.bootkube.etcd_peer_key}"
}
providers = {
docker = "docker.sydney"
}
}
module "bootkube" {
source = "git::https://github.com/poseidon/terraform-render-bootkube.git?ref=bcbdddd8d07c99ab88b2e9ebfb662de4c104de0a"
cluster_name = "k8s.bb8.fun"
api_servers = ["k8s.bb8.fun"]
cluster_domain_suffix = "k8s.bb8.fun"
etcd_servers = ["etcd.bb8.fun"]
asset_dir = "./k8s"
}

129
main.tf
View File

@ -1,103 +1,112 @@
module "cloudflare" {
source = "cloudflare"
domain = "bb8.fun"
ips = "${var.ips}"
source = "./cloudflare"
domain = "bb8.fun"
zone_id = lookup(data.cloudflare_zones.bb8.zones[0], "id")
ips = var.ips
droplet_ip = module.digitalocean.droplet_ipv4
}
module "docker" {
source = "docker"
web_username = "${var.web_username}"
web_password = "${var.web_password}"
cloudflare_key = "${var.cloudflare_key}"
source = "./docker"
web_username = data.pass_password.web_username.password
web_password = data.pass_password.web_password.password
cloudflare_key = data.pass_password.cloudflare_key.password
cloudflare_email = "bb8@captnemo.in"
wiki_session_secret = "${var.wiki_session_secret}"
networks-mongorocks = "${module.db.networks-mongorocks}"
ips = "${var.ips}"
wiki_session_secret = data.pass_password.wiki_session_secret.password
ips = var.ips
domain = "bb8.fun"
}
module "db" {
source = "db"
postgres-root-password = "${var.postgres-root-password}"
ips = "${var.ips}"
source = "./db"
postgres-root-password = data.pass_password.postgres-root-password.password
ips = var.ips
}
module "timemachine" {
source = "timemachine"
ips = "${var.ips}"
source = "./timemachine"
ips = var.ips
username-1 = "vikalp"
password-1 = "${var.timemachine-password-1}"
username-2 = "rishav"
password-2 = "${var.timemachine-password-2}"
password-1 = data.pass_password.timemachine-password-1.password
password-2 = data.pass_password.timemachine-password-2.password
}
module "gitea" {
source = "gitea"
domain = "git.captnemo.in"
traefik-labels = "${var.traefik-common-labels}"
ips = "${var.ips}"
secret-key = "${var.gitea-secret-key}"
internal-token = "${var.gitea-internal-token}"
smtp-password = "${var.gitea-smtp-password}"
lfs-jwt-secret = "${var.gitea-lfs-jwt-secret}"
mysql-password = "${var.gitea-mysql-password}"
source = "./gitea"
domain = "git.captnemo.in"
traefik-labels = var.traefik-common-labels
ips = var.ips
secret-key = data.pass_password.gitea-secret-key.password
internal-token = data.pass_password.gitea-internal-token.password
smtp-password = data.pass_password.gitea-smtp-password.password
lfs-jwt-secret = data.pass_password.gitea-lfs-jwt-secret.password
oauth2-jwt-secret = data.pass_password.gitea-oauth2-jwt-secret.password
traefik-network-id = "${module.docker.traefik-network-id}"
//passed, but not used
mysql-password = ""
traefik-network-id = module.docker.traefik-network-id
}
module "opml" {
source = "opml"
source = "./opml"
domain = "opml.bb8.fun"
client-id = "${var.opml-github-client-id}"
client-secret = "${var.opml-github-client-secret}"
traefik-network-id = "${module.docker.traefik-network-id}"
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" {
source = "radicale"
source = "./radicale"
domain = "radicale.bb8.fun"
}
module "resilio" {
source = "resilio"
domain = "sync.bb8.fun"
traefik-labels = "${var.traefik-common-labels}"
ips = "${var.ips}"
traefik-network-id = "${module.docker.traefik-network-id}"
}
module "media" {
source = "media"
source = "./media"
domain = "bb8.fun"
traefik-labels = "${var.traefik-common-labels}"
ips = "${var.ips}"
traefik-network-id = "${module.docker.traefik-network-id}"
traefik-labels = var.traefik-common-labels
ips = var.ips
# ToDO: Change this to lookup
traefik-network-id = "ffc1e366849e"
lastfm_api_key = data.pass_password.navidrome-lastfm-api-key.password
lastfm_secret = data.pass_password.navidrome-lastfm-secret.password
spotify_id = data.pass_password.navidrome-spotify-id.password
spotify_secret = data.pass_password.navidrome-spotify-secret.password
}
module "monitoring" {
source = "monitoring"
gf-security-admin-password = "${var.gf-security-admin-password}"
source = "./monitoring"
gf-security-admin-password = data.pass_password.gf-security-admin-password.password
domain = "bb8.fun"
transmission = "${module.media.names-transmission}"
traefik-labels = "${var.traefik-common-labels}"
ips = "${var.ips}"
links-traefik = "${module.docker.names-traefik}"
traefik-network-id = "${module.docker.traefik-network-id}"
transmission = module.media.names-transmission
traefik-labels = var.traefik-common-labels
ips = var.ips
links-traefik = module.docker.names-traefik
traefik-network-id = module.docker.traefik-network-id
}
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"
# source = "./tinyproxy"
# ips = "${var.ips}"
# }
module "abstruse" {
source = "abstruse"
domain = "ci.bb8.fun"
traefik-labels = "${var.traefik-common-labels}"
traefik-network-id = "${module.docker.traefik-network-id}"
}

29
mastodon/db.tf Normal file
View File

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

23
mastodon/locals.tf Normal file
View File

@ -0,0 +1,23 @@
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",
]
}

103
mastodon/main.tf Normal file
View File

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

5
mastodon/network.tf Normal file
View File

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

10
mastodon/provider.tf Normal file
View File

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

18
mastodon/vars.tf Normal file
View File

@ -0,0 +1,18 @@
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,74 +1,62 @@
module "airsonic" {
source = "../modules/container"
image = "linuxserver/airsonic:latest"
name = "airsonic"
resource {
memory = "1024"
}
web {
port = 4040
host = "airsonic.bb8.fun"
expose = true
}
env = [
"PUID=1004",
"PGID=1003",
"TZ=Asia/Kolkata",
"JAVA_OPTS=-Xmx512m -Dserver.use-forward-headers=true -Dserver.context-path=/",
]
devices = [{
host_path = "/dev/snd"
container_path = "/dev/snd"
}]
# files = [
# "/usr/lib/jvm/java-1.8-openjdk/jre/lib/airsonic.properties",
# "/usr/lib/jvm/java-1.8-openjdk/jre/lib/sound.properties",
# ]
# contents = [
# "${data.template_file.airsonic-properties-file.rendered}",
# "${file("${path.module}/conf/airsonic.sound.properties")}",
# ]
volumes = [
{
host_path = "/mnt/xwing/config/airsonic2"
container_path = "/config"
},
{
host_path = "/mnt/xwing/media/Music"
container_path = "/music"
},
{
host_path = "/mnt/xwing/config/airsonic/playlists"
container_path = "/playlists"
},
{
host_path = "/mnt/xwing/config/airsonic/podcasts"
container_path = "/podcasts"
},
{
host_path = "/mnt/xwing/config/airsonic/jre"
container_path = "/usr/lib/jvm/java-1.8-openjdk/jre/lib/"
},
]
}
# module "airsonic" {
# source = "../modules/container"
# image = "linuxserver/airsonic:latest"
# name = "airsonic"
# resource {
# memory = "1024"
# memory_swap = "1024"
# }
# web {
# port = 4040
# host = "airsonic.bb8.fun"
# expose = true
# }
# networks = "${list(docker_network.media.id, data.docker_network.bridge.id)}"
# env = [
# "PUID=1004",
# "PGID=1003",
# "TZ=Asia/Kolkata",
# "JAVA_OPTS=-Xmx512m -Dserver.use-forward-headers=true -Dserver.context-path=/",
# ]
# devices = [{
# host_path = "/dev/snd"
# container_path = "/dev/snd"
# }]
# # files = [
# # "/usr/lib/jvm/java-1.8-openjdk/jre/lib/airsonic.properties",
# # "/usr/lib/jvm/java-1.8-openjdk/jre/lib/sound.properties",
# # ]
# # contents = [
# # "${data.template_file.airsonic-properties-file.rendered}",
# # "${file("${path.module}/conf/airsonic.sound.properties")}",
# # ]
# volumes = [
# {
# host_path = "/mnt/xwing/config/airsonic2"
# container_path = "/config"
# },
# {
# host_path = "/mnt/xwing/media/Music"
# container_path = "/music"
# },
# {
# host_path = "/mnt/xwing/config/airsonic/playlists"
# container_path = "/playlists"
# },
# {
# host_path = "/mnt/xwing/config/airsonic/podcasts"
# container_path = "/podcasts"
# },
# {
# host_path = "/mnt/xwing/config/airsonic/jre"
# container_path = "/usr/lib/jvm/java-1.8-openjdk/jre/lib/"
# },
# ]
# }
# data "template_file" "airsonic-properties-file" {
# template = "${file("${path.module}/conf/airsonic.properties.tpl")}"
# vars {
# smtp-password = "${var.airsonic-smtp-password}"
# # db-password = "${var.airsonic-db-password}"
# }
# }

View File

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

4
media/data.tf Normal file
View File

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

View File

@ -1,47 +1,74 @@
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.latest}"
image = docker_image.emby.image_id
# SSD holds both the cache and data
volumes {
host_path = "/mnt/xwing/config/emby"
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"
}
labels = "${merge(
var.traefik-labels,
map(
"traefik.frontend.rule", "Host:emby.in.${var.domain},emby.${var.domain}",
"traefik.frontend.passHostHeader", "true",
"traefik.port", 8096,
))}"
dynamic "labels" {
for_each = local.emby_labels
content {
label = labels.key
value = labels.value
}
}
networks = ["${docker_network.media.id}", "${var.traefik-network-id}"]
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 = [
"APP_USER=lounge",
"APP_UID=1004",
"APP_GID=1003",
"APP_CONFIG=/mnt/xwing/config",
"TZ=Asia/Kolkata",
"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}"]
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

@ -2,20 +2,25 @@ module "jackett" {
name = "jackett"
source = "../modules/container"
image = "linuxserver/jackett:latest"
# TODO FIXME
# networks = [data.docker_network.bridge.id]
web {
web = {
expose = true
port = 9117
host = "jackett.${var.domain}"
}
volumes = [{
host_path = "/mnt/xwing/config/jackett"
container_path = "/config"
}]
volumes = [
{
host_path = "/mnt/xwing/config/jackett"
container_path = "/config"
},
]
resource {
memory = "256"
resource = {
memory = "256"
memory_swap = "512"
}
env = [
@ -24,3 +29,4 @@ module "jackett" {
"TZ=Asia/Kolkata",
]
}

View File

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

50
media/navidrome.tf Normal file
View File

@ -0,0 +1,50 @@
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

@ -3,7 +3,7 @@ resource "docker_network" "media" {
driver = "bridge"
ipam_config {
subnet = "172.18.0.0/16"
subnet = "172.18.0.0/24"
gateway = "172.18.0.1"
}
}

View File

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

19
media/providers.tf Normal file
View File

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

33
media/prowlarr.tf Normal file
View File

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

View File

@ -3,22 +3,29 @@ module "radarr" {
source = "../modules/container"
image = "linuxserver/radarr:latest"
web {
networks = [docker_network.media.id, data.docker_network.bridge.id]
web = {
expose = true
port = 7878
host = "radarr.${var.domain}"
}
resource {
resource = {
memory = 512
memory_swap = 1024
}
volumes = [
{
host_path = "/mnt/xwing/config/radarr"
host_path = "/mnt/zwing/config/radarr"
container_path = "/config"
},
# Backups stay on spinning disks
{
host_path = "/mnt/xwing/backups/config/sonarr"
container_path = "/config/Backups"
},
{
host_path = "/mnt/xwing/media/DL"
container_path = "/downloads"
@ -35,3 +42,4 @@ module "radarr" {
"TZ=Asia/Kolkata",
]
}

26
media/requestrr.tf Normal file
View File

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

View File

@ -3,22 +3,27 @@ module "sonarr-container" {
source = "../modules/container"
image = "linuxserver/sonarr:latest"
web {
web = {
expose = true
port = 8989
host = "sonarr.${var.domain}"
}
resource {
resource = {
memory = 512
memory_swap = 1024
}
volumes = [
{
host_path = "/mnt/xwing/config/sonarr"
host_path = "/mnt/zwing/config/sonarr"
container_path = "/config"
},
# Backups stay on spinning disks
{
host_path = "/mnt/xwing/backups/config/sonarr"
container_path = "/config/Backups"
},
{
host_path = "/mnt/xwing/media/DL"
container_path = "/downloads"
@ -35,5 +40,6 @@ module "sonarr-container" {
"TZ=Asia/Kolkata",
]
networks = "${list(docker_network.media.id)}"
networks = [docker_network.media.id, data.docker_network.bridge.id]
}

View File

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

View File

@ -1,11 +1,11 @@
variable "domain" {
type = "string"
type = string
}
# variable "airsonic-smtp-password" {}
variable "traefik-labels" {
type = "map"
type = map(string)
}
// TODO: Remove duplication
@ -14,7 +14,29 @@ variable "basic_auth" {
}
variable "ips" {
type = "map"
type = map(string)
}
variable "traefik-network-id" {
}
variable "lastfm_api_key" {
description = "Navidrome Configuration for lastfm_api_key"
type = string
}
variable "lastfm_secret" {
description = "Navidrome Configuration for lastfm_secret"
type = string
}
variable "spotify_id" {
description = "Navidrome Configuration for spotify_id"
type = string
}
variable "spotify_secret" {
description = "Navidrome Configuration for spotify_secret"
type = string
}
variable "traefik-network-id" {}

View File

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

View File

@ -1,227 +0,0 @@
resource "docker_container" "bootkube" {
image = "${docker_image.image.latest}"
name = "bootkube"
volumes {
container_path = "/etc/kubernetes"
host_path = "/etc/kubernetes"
}
# bootstrap manifests
upload {
content = "${file("${var.asset-dir}/bootstrap-manifests/bootstrap-apiserver.yaml")}"
file = "/home/.bootkube/bootstrap-manifests/bootstrap-apiserver.yaml"
}
upload {
content = "${file("${var.asset-dir}/bootstrap-manifests/bootstrap-controller-manager.yaml")}"
file = "/home/.bootkube/bootstrap-manifests/bootstrap-controller-manager.yaml"
}
upload {
content = "${file("${var.asset-dir}/bootstrap-manifests/bootstrap-scheduler.yaml")}"
file = "/home/.bootkube/bootstrap-manifests/bootstrap-scheduler.yaml"
}
# etcd secrets
#
upload {
file = "/home/.bootkube/tls/etcd-client-ca.crt"
content = "${file("${var.asset-dir}/tls/etcd-client-ca.crt")}"
}
upload {
file = "/home/.bootkube/tls/etcd-client.crt"
content = "${file("${var.asset-dir}/tls/etcd-client.crt")}"
}
upload {
file = "/home/.bootkube/tls/etcd-client.key"
content = "${file("${var.asset-dir}/tls/etcd-client.key")}"
}
# Cluster Networking
upload {
content = "${file("${var.asset-dir}/manifests-networking/cluster-role-binding.yaml")}"
file = "/home/.bootkube/manifests/networking-cluster-role-binding.yaml"
}
upload {
content = "${file("${var.asset-dir}/manifests-networking/cluster-role.yaml")}"
file = "/home/.bootkube/manifests/networking-cluster-role.yaml"
}
upload {
content = "${file("${var.asset-dir}/manifests-networking/config.yaml")}"
file = "/home/.bootkube/manifests/networking-config.yaml"
}
upload {
content = "${file("${var.asset-dir}/manifests-networking/daemonset.yaml")}"
file = "/home/.bootkube/manifests/networking-daemonset.yaml"
}
upload {
content = "${file("${var.asset-dir}/manifests-networking/service-account.yaml")}"
file = "/home/.bootkube/manifests/networking-service-account.yaml"
}
# TLS
upload {
file = "/home/.bootkube/tls/service-account.pub"
content = "${file("${var.asset-dir}/tls/service-account.pub")}"
}
upload {
file = "/home/.bootkube/tls/service-account.key"
content = "${file("${var.asset-dir}/tls/service-account.key")}"
}
upload {
content = "${file("${var.asset-dir}/tls/ca.key")}"
file = "/home/.bootkube/tls/ca.key"
}
upload {
content = "${file("${var.asset-dir}/tls/ca.crt")}"
file = "/home/.bootkube/tls/ca.crt"
}
upload {
content = "${file("${var.asset-dir}/tls/apiserver.key")}"
file = "/home/.bootkube/tls/apiserver.key"
}
upload {
content = "${file("${var.asset-dir}/tls/apiserver.crt")}"
file = "/home/.bootkube/tls/apiserver.crt"
}
upload {
content = "${var.assets["kubelet_cert"]}"
file = "/home/.bootkube/tls/kubelet.crt"
}
upload {
content = "${var.assets["kubelet_key"]}"
file = "/home/.bootkube/tls/kubelet.key"
}
# TODO: Generate Filenames Dynamically
# TODO: Check if this is needed at all
upload {
content = "${file("${var.asset-dir}/auth/k8s.bb8.fun-config")}"
file = "/home/.bootkube/auth/k8s.bb8.fun-config"
}
# auth/kubeconfig-kubelet
upload {
content = "${var.assets["kubeconfig-kubelet"]}"
file = "/home/.bootkube/auth/kubeconfig-kubelet"
}
# TODO: Move to a module read instead of file
# auth/kubeconfig
upload {
file = "/home/.bootkube/auth/kubeconfig"
content = "${file("${var.asset-dir}/auth/kubeconfig")}"
}
# Manifests Directory
upload {
file = "/home/.bootkube/manifests/kube-apiserver-role-binding.yaml"
content = "${file("${var.asset-dir}/manifests/kube-apiserver-role-binding.yaml")}"
}
upload {
file = "/home/.bootkube/manifests/kube-apiserver-sa.yaml"
content = "${file("${var.asset-dir}/manifests/kube-apiserver-sa.yaml")}"
}
upload {
file = "/home/.bootkube/manifests/kube-apiserver-secret.yaml"
content = "${file("${var.asset-dir}/manifests/kube-apiserver-secret.yaml")}"
}
upload {
file = "/home/.bootkube/manifests/kube-apiserver.yaml"
content = "${file("${var.asset-dir}/manifests/kube-apiserver.yaml")}"
}
upload {
file = "/home/.bootkube/manifests/kubeconfig-in-cluster.yaml"
content = "${file("${var.asset-dir}/manifests/kubeconfig-in-cluster.yaml")}"
}
upload {
file = "/home/.bootkube/manifests/kube-controller-manager-disruption.yaml"
content = "${file("${var.asset-dir}/manifests/kube-controller-manager-disruption.yaml")}"
}
upload {
file = "/home/.bootkube/manifests/kube-controller-manager-role-binding.yaml"
content = "${file("${var.asset-dir}/manifests/kube-controller-manager-role-binding.yaml")}"
}
upload {
file = "/home/.bootkube/manifests/kube-controller-manager-sa.yaml"
content = "${file("${var.asset-dir}/manifests/kube-controller-manager-sa.yaml")}"
}
upload {
file = "/home/.bootkube/manifests/kube-controller-manager-secret.yaml"
content = "${file("${var.asset-dir}/manifests/kube-controller-manager-secret.yaml")}"
}
upload {
file = "/home/.bootkube/manifests/kube-controller-manager.yaml"
content = "${file("${var.asset-dir}/manifests/kube-controller-manager.yaml")}"
}
upload {
file = "/home/.bootkube/manifests/kubelet-nodes-cluster-role-binding.yaml"
content = "${file("${var.asset-dir}/manifests/kubelet-nodes-cluster-role-binding.yaml")}"
}
upload {
file = "/home/.bootkube/manifests/kube-proxy-role-binding.yaml"
content = "${file("${var.asset-dir}/manifests/kube-proxy-role-binding.yaml")}"
}
upload {
file = "/home/.bootkube/manifests/kube-proxy-sa.yaml"
content = "${file("${var.asset-dir}/manifests/kube-proxy-sa.yaml")}"
}
upload {
file = "/home/.bootkube/manifests/kube-proxy.yaml"
content = "${file("${var.asset-dir}/manifests/kube-proxy.yaml")}"
}
upload {
file = "/home/.bootkube/manifests/kube-scheduler-disruption.yaml"
content = "${file("${var.asset-dir}/manifests/kube-scheduler-disruption.yaml")}"
}
upload {
file = "/home/.bootkube/manifests/kube-scheduler-role-binding.yaml"
content = "${file("${var.asset-dir}/manifests/kube-scheduler-role-binding.yaml")}"
}
upload {
file = "/home/.bootkube/manifests/kube-scheduler-sa.yaml"
content = "${file("${var.asset-dir}/manifests/kube-scheduler-sa.yaml")}"
}
upload {
file = "/home/.bootkube/manifests/kube-scheduler-volume-scheduler-role-binding.yaml"
content = "${file("${var.asset-dir}/manifests/kube-scheduler-volume-scheduler-role-binding.yaml")}"
}
upload {
file = "/home/.bootkube/manifests/kube-scheduler.yaml"
content = "${file("${var.asset-dir}/manifests/kube-scheduler.yaml")}"
}
upload {
file = "/home/.bootkube/manifests/pod-checkpointer-cluster-role-binding.yaml"
content = "${file("${var.asset-dir}/manifests/pod-checkpointer-cluster-role-binding.yaml")}"
}
upload {
file = "/home/.bootkube/manifests/pod-checkpointer-cluster-role.yaml"
content = "${file("${var.asset-dir}/manifests/pod-checkpointer-cluster-role.yaml")}"
}
upload {
file = "/home/.bootkube/manifests/pod-checkpointer-role-binding.yaml"
content = "${file("${var.asset-dir}/manifests/pod-checkpointer-role-binding.yaml")}"
}
upload {
file = "/home/.bootkube/manifests/pod-checkpointer-role.yaml"
content = "${file("${var.asset-dir}/manifests/pod-checkpointer-role.yaml")}"
}
upload {
file = "/home/.bootkube/manifests/pod-checkpointer-sa.yaml"
content = "${file("${var.asset-dir}/manifests/pod-checkpointer-sa.yaml")}"
}
upload {
file = "/home/.bootkube/manifests/pod-checkpointer.yaml"
content = "${file("${var.asset-dir}/manifests/pod-checkpointer.yaml")}"
}
command = [
"/bootkube",
"start",
"--asset-dir=/home/.bootkube",
]
network_mode = "host"
restart = "on-failure"
max_retry_count = 5
}
data "docker_registry_image" "image" {
name = "quay.io/coreos/bootkube:v${var.version}"
}
resource "docker_image" "image" {
name = "${data.docker_registry_image.image.name}"
pull_triggers = ["${data.docker_registry_image.image.sha256_digest}"]
}

View File

@ -1,13 +0,0 @@
# output "exit_code" {
# # TODO: Pick correct exit code
# # value = "${coalesce(formatlist("%s", docker_container.render.*.exit_code))}"
# # See https://github.com/hashicorp/terraform/issues/15165
# value = "${var.mode == "render" ?
# "${element(concat(docker_container.render.*.exit_code, list("")), 0)}" :
# "${element(concat(docker_container.start.*.exit_code, list("")), 0)}"
# }"
# }
output "image" {
value = "${docker_image.image.latest}"
}

View File

@ -1,41 +0,0 @@
// Based on https://github.com/v1k0d3n/dockerfiles/tree/master/bootkube
variable "k8s_host" {
description = "kubenetes hostname"
}
variable "host_port" {
default = "8443"
}
variable "network_provider" {
default = "flannel"
}
variable "host_ip" {}
variable "pod_cidr" {
default = "10.25.0.0/16"
}
variable "service_cidr" {
default = "10.96.0.0/16"
}
variable "mode" {}
variable "version" {
default = "0.14.0"
}
variable "depends_on" {
default = []
type = "list"
}
variable "assets" {
type = "map"
}
variable "asset-dir" {}

View File

@ -0,0 +1,9 @@
data "docker_registry_image" "image" {
name = var.image
}
resource "docker_image" "image" {
name = var.image
pull_triggers = [data.docker_registry_image.image.sha256_digest]
keep_locally = var.keep_image
}

View File

@ -1,36 +1,49 @@
locals {
default_labels {
default_labels = {
"managed.by" = "nebula"
}
web {
"traefik.port" = "${lookup(var.web, "port", "80")}"
"traefik.frontend.rule" = "Host:${lookup(var.web, "host", "example.invalid")}"
"traefik.protocol" = "${lookup(var.web, "protocol", "http")}"
web = {
"traefik.port" = var.web.port != null ? var.web.port : 80
"traefik.frontend.rule" = var.web.host != null ? "Host:${var.web.host}" : "Host:example.invalid"
"traefik.protocol" = var.web.protocol != null ? var.web.protocol : "http"
}
resource {
memory = "${lookup(var.resource, "memory", 64)}"
memory_swap = "${lookup(var.resource, "memory_swap", 128)}"
}
traefik_common_labels {
traefik_common_labels = {
"traefik.enable" = "true"
// HSTS
"traefik.frontend.headers.SSLTemporaryRedirect" = "true"
"traefik.frontend.headers.STSSeconds" = "2592000"
"traefik.frontend.headers.STSIncludeSubdomains" = "false"
// X-Powered-By, Server headers
"traefik.frontend.headers.customResponseHeaders" = "${var.xpoweredby}"
"traefik.frontend.headers.customResponseHeaders" = var.xpoweredby
"traefik.frontend.headers.contentTypeNosniff" = "true"
"traefik.frontend.headers.browserXSSFilter" = "true"
"traefik.docker.network" = "traefik"
"traefik.docker.network" = "traefik"
}
traefik_auth_labels {
"traefik.frontend.auth.basic" = "${var.auth_header}"
# if var.web.auth == true
traefik_auth_labels = {
"traefik.frontend.auth.basic" = var.auth_header
}
resource = {
memory = lookup(var.resource, "memory", 64)
memory_swap = lookup(var.resource, "memory_swap", 128)
}
labels = merge(
# Default labels are applied to every container
local.default_labels,
# Add the common traefik labels
var.web.expose ? local.traefik_common_labels : null,
# Apply the overwritten web labels only if the container is exposed
var.web.expose ? local.web : null,
# And finally a label for Basic Authentication if the service wants it
var.web.auth != null ? (var.web.auth ? local.traefik_auth_labels : null) : null,
var.labels,
)
networks = concat(var.networks, var.web.expose ? ["traefik"] : [])
}

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