Pulumi code for my server setup
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

add unbound

+144 -79
+40 -38
lib/service/service.ts
··· 47 47 48 48 // TODO: turn ContainerService into a factory function like https://sst.dev/docs/examples/#api-gateway-auth 49 49 class ContainerService extends pulumi.ComponentResource { 50 - public readonly container: docker.Container | undefined; 50 + public readonly container: Output<docker.Container> | undefined; 51 51 public readonly localUrl: Output<string> | undefined; 52 52 public readonly remoteUrl: string | undefined; 53 53 public readonly ip: Output<string | undefined> | undefined; ··· 194 194 capabilities.drops &&= capabilities.drops.map(ensureCapPrefix); 195 195 } 196 196 197 - this.container = new docker.Container( 198 - name, 199 - { 200 - ...args, 201 - image, 202 - ...(opts?.deleteBeforeReplace !== false && { name: args.name ?? name }), 203 - command: args.command, 204 - restart: args.restart ?? "unless-stopped", 205 - labels: allLabels.apply(convertLabels), 206 - envs: convertEnvs(args.envs), 207 - ports: convertPorts(args.ports), 208 - mounts, 209 - volumes: args.volumes, 210 - logDriver: "local", 211 - networkMode: args.networkMode ?? "bridge", 212 - // TODO: healthchecks 213 - // healthcheck: {tests} 214 - networksAdvanced: args.networkMode 215 - ? [] 216 - : pulumi 217 - .output(args.networksAdvanced) 218 - .apply((networksAdvanced) => [...networksAdvanced, { name: defaultNetwork.name }]), 219 - hosts: args.networkMode 220 - ? [] 221 - : pulumi 222 - .output(args.hosts) 223 - .apply((hosts) => [{ host: "host.docker.internal", ip: "host-gateway" }, ...hosts]), 224 - capabilities, 225 - }, 226 - { 227 - parent: this, 228 - deleteBeforeReplace: true, 229 - replaceOnChanges: ["mounts", "volumes"], 230 - ignoreChanges: opts?.ignoreChanges, 231 - dependsOn: this.dependsOn, 232 - ...opts, 233 - }, 197 + this.container = output( 198 + new docker.Container( 199 + name, 200 + { 201 + ...args, 202 + image, 203 + ...(opts?.deleteBeforeReplace !== false && { name: args.name ?? name }), 204 + command: args.command, 205 + restart: args.restart ?? "unless-stopped", 206 + labels: allLabels.apply(convertLabels), 207 + envs: convertEnvs(args.envs), 208 + ports: convertPorts(args.ports), 209 + mounts, 210 + volumes: args.volumes, 211 + logDriver: "local", 212 + networkMode: args.networkMode ?? "bridge", 213 + // TODO: healthchecks 214 + // healthcheck: {tests} 215 + networksAdvanced: args.networkMode 216 + ? [] 217 + : pulumi 218 + .output(args.networksAdvanced) 219 + .apply((networksAdvanced) => [...networksAdvanced, { name: defaultNetwork.name }]), 220 + hosts: args.networkMode 221 + ? [] 222 + : pulumi 223 + .output(args.hosts) 224 + .apply((hosts) => [{ host: "host.docker.internal", ip: "host-gateway" }, ...hosts]), 225 + capabilities, 226 + }, 227 + { 228 + parent: this, 229 + deleteBeforeReplace: true, 230 + replaceOnChanges: ["mounts", "volumes"], 231 + ignoreChanges: opts?.ignoreChanges, 232 + dependsOn: this.dependsOn, 233 + ...opts, 234 + }, 235 + ), 234 236 ); 235 237 236 238 this.ip = pulumi
+34 -26
services/haring/atproto/relay.ts
··· 3 3 import { getEnv } from "~lib/env"; 4 4 import { interpolate } from "@pulumi/pulumi"; 5 5 import { confMount, dataMount } from "~lib/service/mounts"; 6 - import { getLatestCommit } from "~lib/util"; 6 + import { ensure, getLatestCommit } from "~lib/util"; 7 + import { UNBOUND_ADDRESS, unboundService } from "../networking/unbound/unbound"; 7 8 8 9 const postgresRelayService = new ContainerService("postgres-relay", { 9 10 image: "postgres", ··· 42 43 }, 43 44 ); 44 45 45 - export const relayService = new ContainerService("relay", { 46 - localImage: interpolate`${relayImage.ref}@${relayImage.digest}`, 47 - servicePort: 2470, 48 - networkMode: "host", 49 - mounts: [dataMount("media/relay", "/data/relay/persist")], 50 - middlewares: ["relay"], 51 - envs: { 52 - RELAY_ADMIN_PASSWORD: getEnv("RELAY_ADMIN_PASSWORD"), 53 - DATABASE_URL: interpolate`postgres://postgres:${getEnv("POSTGRES_PASSWORD")}@${postgresRelayService.ip}/relay`, 54 - RELAY_PERSIST_DIR: "/data/relay/persist", 55 - RELAY_REPLAY_WINDOW: "24h", 56 - RELAY_TRUSTED_DOMAINS: [ 57 - "*.host.bsky.network", 58 - "atproto.brid.gy", 59 - "blacksky.app", 60 - "northsky.social", 61 - "tngl.sh", 62 - "pds.sprk.so", 63 - "roomy.chat", 64 - "selfhosted.social", 65 - "eurosky.social", 66 - "pds.witchcraft.systems", 67 - "npmx.social", 68 - ], 46 + export const relayService = new ContainerService( 47 + "relay", 48 + { 49 + localImage: interpolate`${relayImage.ref}@${relayImage.digest}`, 50 + servicePort: 2470, 51 + networkMode: "host", 52 + mounts: [dataMount("media/relay", "/data/relay/persist")], 53 + middlewares: ["relay"], 54 + dns: [UNBOUND_ADDRESS], 55 + envs: { 56 + RELAY_ADMIN_PASSWORD: getEnv("RELAY_ADMIN_PASSWORD"), 57 + DATABASE_URL: interpolate`postgres://postgres:${getEnv("POSTGRES_PASSWORD")}@${postgresRelayService.ip}/relay`, 58 + RELAY_PERSIST_DIR: "/data/relay/persist", 59 + RELAY_REPLAY_WINDOW: "24h", 60 + RELAY_TRUSTED_DOMAINS: [ 61 + "*.host.bsky.network", 62 + "atproto.brid.gy", 63 + "blacksky.app", 64 + "northsky.social", 65 + "tngl.sh", 66 + "pds.sprk.so", 67 + "roomy.chat", 68 + "selfhosted.social", 69 + "eurosky.social", 70 + "pds.witchcraft.systems", 71 + "npmx.social", 72 + ], 73 + }, 74 + }, 75 + { 76 + dependsOn: unboundService.container, 69 77 }, 70 - }); 78 + );
+1 -1
services/haring/atproto/tranquil.ts services/haring/atproto/tranquil/tranquil.ts
··· 50 50 let tranquilService: ContainerService | undefined; 51 51 52 52 if (postgresTranquilService.container) { 53 - const msmtprcFile = new asset.FileAsset(`${import.meta.dirname}/tranquil-files/msmtprc`); 53 + const msmtprcFile = new asset.FileAsset(path.join(import.meta.dirname, "msmtprc")); 54 54 const copyMsmtprc = new remote.CopyToRemote("tranquil-msmtprc", { 55 55 connection: defaultConnection, 56 56 source: msmtprcFile,
+13 -13
services/haring/files/nextcloud.ts
··· 3 3 import { confMount, ssdcacheMount } from "~lib/service/mounts"; 4 4 import { ContainerService } from "~lib/service/service"; 5 5 6 - export const nextCloudService = new ContainerService("nextcloud", { 6 + export const nextcloudService = new ContainerService("nextcloud", { 7 7 servicePort: 443, 8 8 mounts: [ 9 9 confMount("nextcloud"), ··· 12 12 ], 13 13 envs: { 14 14 DOCKER_MODS: "linuxserver/mods:nextcloud-notify-push|linuxserver/mods:nextcloud-mediadc", 15 - DATABASE_URL: interpolate`postgres://postgres:${getEnv("POSTGRES_PASSWORD")}@postgres/nextcloud`, 15 + DATABASE_URL: interpolate`postgres://postgres:${getEnv("POSTGRES_PASSWORD")}@postgres-nextcloud/nextcloud`, 16 16 DATABASE_PREFIX: "oc_", 17 - REDIS_URL: interpolate`redis://default:${getEnv("VALKEY_PASSWORD")}@valkey`, 17 + REDIS_URL: interpolate`redis://default:${getEnv("VALKEY_PASSWORD")}@valkey-nextcloud`, 18 18 NEXTCLOUD_URL: "https://nextcloud.bas.sh", 19 19 }, 20 20 }); 21 21 22 - if (nextCloudService.container) { 23 - const valkeyService = new ContainerService("valkey", { 22 + if (nextcloudService.container) { 23 + const valkeyNextcloudService = new ContainerService("valkey-nextcloud", { 24 24 image: "valkey/valkey", 25 - command: [interpolate`--requirepass ${getEnv("VALKEY_PASSWORD")}`], 25 + command: [ 26 + interpolate`--requirepass ${getEnv("VALKEY_PASSWORD")}`, 27 + "--save 60", 28 + "--loglevel warning", 29 + ], 30 + volumes: [{ volumeName: "valkey-unbound", containerPath: "/data" }], 26 31 }); 27 32 28 - const postgresService = new ContainerService("postgres", { 33 + const postgresService = new ContainerService("postgres-nextcloud", { 29 34 image: "postgres", 30 - volumes: [ 31 - { 32 - volumeName: "postgres", 33 - containerPath: "/var/lib/postgresql", 34 - }, 35 - ], 35 + volumes: [{ volumeName: "postgres-nextcloud", containerPath: "/var/lib/postgresql" }], 36 36 envs: { 37 37 POSTGRES_PASSWORD: getEnv("POSTGRES_PASSWORD"), 38 38 POSTGRES_DB: "nextcloud",
+2 -1
services/haring/index.ts
··· 35 35 export * from "./networking/tailscale"; 36 36 export * from "./networking/tinyproxy"; 37 37 export * from "./networking/wireguard"; 38 + export * from "./networking/unbound/unbound"; 38 39 39 40 // export * from "./downloaders/jdownloader"; 40 41 export * from "./downloaders/qbittorrent"; ··· 54 55 export * from "./files/stash"; 55 56 export * from "./files/synclounge"; 56 57 57 - export * from "./atproto/tranquil"; 58 + export * from "./atproto/tranquil/tranquil"; 58 59 export * from "./atproto/pegasus"; 59 60 export * from "./atproto/pds"; 60 61 export * from "./atproto/relay";
+15
services/haring/networking/unbound/cachedb.conf
··· 1 + server: 2 + module-config: "validator cachedb iterator" 3 + # serve-expired: yes 4 + # serve-expired-ttl: 86400 5 + # serve-expired-client-timeout: 0 6 + # cache-min-ttl: 300 7 + prefetch: yes 8 + msg-cache-size: 64m 9 + rrset-cache-size: 128m 10 + 11 + cachedb: 12 + backend: "redis" 13 + redis-server-host: valkey 14 + redis-server-port: 6379 15 + redis-expire-records: no
+39
services/haring/networking/unbound/unbound.ts
··· 1 + import { remote } from "@pulumi/command"; 2 + import { asset, interpolate } from "@pulumi/pulumi"; 3 + import path from "path"; 4 + import { getEnv } from "~lib/env"; 5 + import { confMount } from "~lib/service/mounts"; 6 + import { defaultNetwork } from "~lib/service/networks"; 7 + import { ContainerService, defaultConnection } from "~lib/service/service"; 8 + 9 + const unboundConfMount = confMount("unbound/custom.conf.d", "/etc/unbound/custom.conf.d"); 10 + 11 + const valkeyUnboundService = new ContainerService("valkey-unbound", { 12 + image: "valkey/valkey", 13 + command: [ 14 + interpolate`--requirepass ${getEnv("VALKEY_PASSWORD")}`, 15 + "--save 300", 16 + "--loglevel warning", 17 + ], 18 + volumes: [{ volumeName: "valkey-unbound", containerPath: "/data" }], 19 + }); 20 + 21 + const unboundConfig = new remote.CopyToRemote("unbound-config", { 22 + connection: defaultConnection, 23 + source: new asset.FileAsset(path.join(import.meta.dirname, "cachedb.conf")), 24 + remotePath: "/home/bas/docker/unbound/cachedb.conf", 25 + }); 26 + 27 + export const UNBOUND_ADDRESS = "172.18.1.1"; 28 + 29 + export const unboundService = new ContainerService( 30 + "unbound", 31 + { 32 + image: "klutchell/unbound", 33 + mounts: [unboundConfMount], 34 + networksAdvanced: [{ name: defaultNetwork.name, ipv4Address: UNBOUND_ADDRESS }], 35 + }, 36 + { 37 + dependsOn: valkeyUnboundService.container, 38 + }, 39 + );