diff --git a/Pulumi.buffed2929.yaml b/Pulumi.buffed2929.yaml deleted file mode 100644 index f12608a..0000000 --- a/Pulumi.buffed2929.yaml +++ /dev/null @@ -1,30 +0,0 @@ -config: - oci:region: eu-zurich-1 - oci:privateKeyPath: pulumi@pomail.fr_2024-03-05T14 33 04.969Z.pem - oci:fingerprint: - secure: AAABABAkZejiW7iEDzCS7EETpb0Cx9AbnpQ7V7ylq8xAIhCWjC0AGl1QyMBTVAGfvhaYugc/Ma48OrqM6udCb43z4/h/W4gm6p9Djg+leA== - oci:tenancyOcid: - secure: AAABAM/qyWPGpopb2T+6jEzaJAa6gvXrVT1XSKh9gn/Pt28tZimyPcR+jRmfBQSFOX/LSfp6TodpP28pgGUUDmnfbvv4bIYFCDMGEhmSb7DmlsedWBy5KZ370GmuHCcTBlYNbFT/rSTEWGIsvU2s - oci:userOcid: - secure: AAABAMHJ6fJebI9aL+4qESzJjU1D8FCAiBckvKfrK+iPCYQJn6qBcRc+Uwz+tsmtssAFnO2/fCtMSpigHYwYc+fbdq6FVj/KSdIlxWkT9HHEW3e2xw7QGhzWz4ZXiYlpj9SHQRmt7mjjOutP - infra-happyDomain:restic_aws_access_key_id: - secure: AAABABCLVz3G4b9//Xa/XBvyMzs9bjGEwnyPOBN7/srMcTeXItWq5+mN/j2upZXh4ogXMP1A38P4pA== - infra-happyDomain:restic_aws_secret_access_key: - secure: AAABAE1v6iqMWEJQ+S5neb2bGldrm1pkePEr1AlIoHFc5Vgi5aASgjdONzbAGNSZK0mT5kRQjTEK0P1I/zQenG3++IHk3zZQPMmZPE+TBaOSo38qEr0bRf4b1yyjWf9C - infra-happyDomain:listmonk_api_username: - secure: AAABAA1C9Rrzc/qN7+J95uRqmSmFGhqB7CJfLdMmhLe2qLKukDlPltg= - infra-happyDomain:listmonk_api_password: - secure: AAABADILUmQsC5STCrsZAa1iTpUZdODtaiMVfS3fTEg+oDAYjAMCZ7D1Qg3K9P8hi6nZ+3Qec8H4V6IcbV+QKQ== - infra-happyDomain:happydomain_ovh_application_secret: - secure: AAABAMByLL376Sd3SezK6+jpHBTBRhMjH00fNgNDyUudQA0blywYe5J7D4wkrgkAfHoSK/bW+p2Wa3sIK1nhBw== - infra-happyDomain:happydomain_ovh_application_key: - secure: AAABAKttTSDZWY1ybyA83+OtsD1TB9t5YLFuN2pL7pECpzfk1bcMVlO5g9EvFDx9 - infra-happyDomain:restic_password: - secure: AAABAGZDQtnRzrocx5zPobqdp2Xp7ABObbGM9+zjRXAOXmX8ioVzSSlQ3pKxqnwsrsquIRSIrUhKmuvfIhWd - infra-happyDomain:happydomain_smtp_user: - secure: AAABACdg/2/ZsMv9/blK4NhYulbdwq/sY32mdIMGqcI55NEUlVTtMZfnKgKbbE0xYVzH2O3euZiJNBvtm0qsmrxi3Wf17UE3PtUZJPZEGkKaaFTh8GF+jcQsaDbkexdc2cNBQFUV6UVkeNJZArtvrnoveLX7HRBFQM+VU5lOQJMAX4Fv1U+UrhBEZS5NES5VVrfDeJ9MXsc49tAwPOC+/6/vjMqNNLhhBXCsSqZbWjRWKw+9Mt2Vo4iOpm8Y6KNO7/BC - infra-happyDomain:happydomain_smtp_password: - secure: AAABAPY64j6ll6m41Rt7ykJ3Mbwy4P++AFl+m7TukGMurQPBHu5HR5M2BxdlWB1SMjGB5w== - infra-happyDomain:region_origin: uk-london-1 - infra-happyDomain:happydomain_beta_jwt_secret_key: - secure: AAABAFA8Cy/ll/KT+y4wRRM3QK2n4q7K00xW3rEobfWPyi45cgTOYtvr2Qu82lhODJFrrq5hAu5ujDjWkW5j8mrkaNu6x6eA+x8IulZc78Owbpdfeith6ysNLe2U/5CJ diff --git a/cloud-init-beta.yaml b/cloud-init-beta.yaml deleted file mode 100644 index 151d1c6..0000000 --- a/cloud-init-beta.yaml +++ /dev/null @@ -1,290 +0,0 @@ -#cloud-config -users: - - default -package_update: true - -packages: - - ca-certificates - - caddy - - cron - - docker.io - - docker-compose-v2 - - jq - - restic - - syslog-ng - -write_files: - - content: | - { - "ip6tables": true, - "ipv6": true, - "fixed-cidr-v6": "fd00:dead:beef::/64", - "userland-proxy": false - } - path: /etc/docker/daemon.json - - content: | - *filter - :INPUT DROP [0:0] - -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT - -A INPUT -p icmpv6 -j ACCEPT - -A INPUT -i lo -j ACCEPT - -A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT - -A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT - -A INPUT -p tcp -m state --state NEW -m tcp --dport 443 -j ACCEPT - -A INPUT -j REJECT --reject-with icmp-host-prohibited - :FORWARD ACCEPT [0:0] - -A FORWARD -j REJECT --reject-with icmp-host-prohibited - :OUTPUT ACCEPT [0:0] - COMMIT - path: /etc/iptables/rules.v6 - - content: | - { - #acme_ca https://acme-staging-v02.api.letsencrypt.org/directory - } - - beta.happydomain.org { - reverse_proxy 127.0.0.1:8081 { - flush_interval -1 - } - } - - betadm.happydomain.org { - basicauth { - nemunaire "$2a$14$niofv0BFHIB4mtpKkhWUy.L8iRDeSdnKsIcSPMk/QNNMPEoFZ94ee" - frederic "$2a$14$niofv0BFHIB4mtpKkhWUy.L8iRDeSdnKsIcSPMk/QNNMPEoFZ94ee" - } - reverse_proxy 127.0.0.1:8082 { - flush_interval -1 - } - } - path: /etc/caddy/Caddyfile - - content: | - @version:3.30 - @include "scl.conf" - - # syslog-ng configuration file. - # - # See syslog-ng(8) and syslog-ng.conf(5) for more information. - - options { - create_dirs(yes); - mark_freq(3600); - stats_freq(43200); - time_reopen(5); - use_dns(no); - dns-cache(no); - owner(root); - group(adm); - perm(0640); - dir_perm(0755); - }; - - source src { system(); internal(); }; - - filter f_auth { facility(auth, authpriv); }; - filter f_emergency { level(emerg); }; - - destination authlog { file("/var/log/auth.log"); }; - destination emergency { file("/var/log/emergency"); }; - - log { source(src); filter(f_auth); destination(authlog); }; - log { source(src); filter(f_emergency); destination(emergency); }; - - # Remote loghost - destination loghost1 { tcp6("geb.ra.nemunai.re"); }; - log { source(src); destination(loghost1); }; - destination loghost2 { tcp6("jizah.masr.nemunai.re"); }; - log { source(src); destination(loghost2); }; - - # Source additional configuration files (.conf extension only) - @include "/etc/syslog-ng/conf.d/*.conf" - path: /etc/syslog-ng/syslog-ng.conf - - content: | - #!/bin/sh - export AWS_ACCESS_KEY_ID=$(cloud-init query ds.metadata.RESTIC_AWS_ACCESS_KEY_ID) - export AWS_SECRET_ACCESS_KEY=$(cloud-init query ds.metadata.RESTIC_AWS_SECRET_ACCESS_KEY) - - export RESTIC_REPOSITORY=$(cloud-init query ds.metadata.RESTIC_REPOSITORY) - export RESTIC_PASSWORD=$(cloud-init query ds.metadata.RESTIC_PASSWORD) - export RESTIC_COMPRESSION=max - - mkdir -p /var/backups/happydomain-beta - - docker exec -i app-happydomain hadmin /api/backup.json -X POST > /var/backups/happydomain-beta/db.json - - restic snapshots > /dev/null 2>&1 || restic init - restic backup /var/backups/happydomain-beta - path: /etc/cron.daily/backup_happydomain - permissions: 0o755 - - content: | - # Static (non-secret) configuration for the happydomain container. - # Secrets injected through cloud-init metadata are written to - # /root/secrets.env by launch_container_app.sh. - HAPPYDOMAIN_BIND=0.0.0.0:8081 - HAPPYDOMAIN_ADMIN_BIND=0.0.0.0:8082 - HAPPYDOMAIN_DEFAULT_NS=172.28.0.53:53 - HAPPYDOMAIN_STORAGE_ENGINE=leveldb - - HAPPYDOMAIN_CAPTCHA_PROVIDER=altcha - HAPPYDOMAIN_DISABLE_REGISTRATION=true - HAPPYDOMAIN_OPT_OUT_INSIGHTS=true - HAPPYDOMAIN_EXTERNALURL=https://beta.happydomain.org - - HAPPYDOMAIN_MAIL_FROM=Fred from happyDomain (beta) - path: /root/beta.env - - content: | - services: - unbound: - image: alpinelinux/unbound - restart: unless-stopped - - configs: - - source: unbound_conf - target: /etc/unbound/unbound.conf - uid: "100" - gid: "101" - - networks: - default: - ipv4_address: 172.28.0.53 - - happydomain: - image: nemunaire/happydomain:${HAPPYDOMAIN_VERSION:-latest} - container_name: app-happydomain - pull_policy: always - ports: - - "127.0.0.1:8081:8081" - - "127.0.0.1:8082:8082" - environment: - # Override some checkers options: use local checkers instead of remote public ones - HAPPYDOMAIN_CHECKER_MATRIXIM_FEDERATIONTESTERSERVER: "http://matrixfederationtester:8080/api/report?server_name=%s" - HAPPYDOMAIN_CHECKER_ZONEMASTER_ZONEMASTERAPIURL: "http://zonemaster:5000" - HAPPYDOMAIN_CHECKER_DNSVIZ_ENDPOINT: "http://dnsviz:8080" - - env_file: - - beta.env - - secrets.env - - dns: - - 172.28.0.53 - networks: - - default - - restart: unless-stopped - - volumes: - - storage:/data:rw - - logging: - driver: syslog - options: - syslog-address: "unixgram:///dev/log" - syslog-facility: daemon - tag: app-happydomain - - dnsviz: - image: happydomain/checker-dnsviz - restart: unless-stopped - - matrixfederationtester: - image: matrixdotorg/federation-tester-backend - environment: - BIND_ADDRESS: "0.0.0.0:8080" - restart: unless-stopped - - zonemaster: - image: zonemaster/backend - command: full - restart: unless-stopped - - configs: - unbound_conf: - content: | - server: - verbosity: 1 - interface: 0.0.0.0 - port: 53 - do-ip4: yes - do-ip6: no - do-udp: yes - do-tcp: yes - - access-control: 127.0.0.0/8 allow - access-control: 172.28.0.0/24 allow - - # Short cache for a testing resolver - cache-max-ttl: 60 - - # Buffers: let the system decide - so-sndbuf: 0 - so-rcvbuf: 0 - - # Trust anchor (static, ships with the image) - trust-anchor-file: "/etc/unbound/root.key" - - volumes: - storage: - - networks: - default: - enable_ipv6: true - ipam: - config: - - subnet: 172.28.0.0/24 - path: /root/docker-compose.yml - - content: | - #!/bin/sh - - [ -z "${HAPPYDOMAIN_VERSION}" ] && export HAPPYDOMAIN_VERSION=$(cloud-init query ds.metadata.HAPPYDOMAIN_VERSION) - - # Secrets injected through cloud-init metadata; the static, non-secret - # configuration lives in /root/beta.env. - cat > /root/secrets.env <> /etc/fstab - - swapon -a - - # Allow traffic in IPv4 - - sed -i '/-A INPUT -j REJECT/i-A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT\n-A INPUT -p tcp -m state --state NEW -m tcp --dport 443 -j ACCEPT' /etc/iptables/rules.v4 - - iptables -I INPUT 5 -p tcp -m state --state NEW -m tcp --dport 443 -j ACCEPT - - iptables -I INPUT 5 -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT - - ip6tables -I INPUT 5 -p tcp -m state --state NEW -m tcp --dport 443 -j ACCEPT - - ip6tables -I INPUT 5 -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT - - # Retrieve last backup (the repo may not exist yet on first boot) - - export AWS_ACCESS_KEY_ID=$(cloud-init query ds.metadata.RESTIC_AWS_ACCESS_KEY_ID) - - export AWS_SECRET_ACCESS_KEY=$(cloud-init query ds.metadata.RESTIC_AWS_SECRET_ACCESS_KEY) - - export RESTIC_PASSWORD=$(cloud-init query ds.metadata.RESTIC_PASSWORD) - - export RESTIC_REPOSITORY=$(cloud-init query ds.metadata.RESTIC_REPOSITORY) - - mkdir -p /var/backups/happydomain-beta - - restic snapshots > /dev/null 2>&1 || restic init - - restic restore latest --target / --include /var/backups/happydomain-beta || true - - # Launch web server (uses /etc/caddy/Caddyfile) - - systemctl enable --now caddy - - systemctl restart caddy - - # Launch container - - /root/launch_container_app.sh - - # Restore happydomain backup - - | - [ -f /var/backups/happydomain-beta/db.json ] && docker exec -i app-happydomain hadmin /api/backup.json -X PUT -d @- < /var/backups/happydomain-beta/db.json diff --git a/consts.go b/consts.go index 1d44470..c66036f 100644 --- a/consts.go +++ b/consts.go @@ -1,4 +1,4 @@ package main const SHAPE_AMD64 = "VM.Standard.E2.1.Micro" -const SSH_AUTHORIZED_KEYS = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIC1d814FsO8ZI5a5iKkUiz12f/oiWwuKtW5BwaZGW1wv nemunaire@khonsou" +const SSH_AUTHORIZED_KEYS = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILO2HHqD/MDYpPjYVMdvYI9Jn1FoyFp43IkPRzjZGvdL nemunaire@oupaout.ra.nemunai.re" diff --git a/host_beta.go b/host_beta.go deleted file mode 100644 index 0ce0952..0000000 --- a/host_beta.go +++ /dev/null @@ -1,93 +0,0 @@ -package main - -import ( - "encoding/base64" - "io/ioutil" - - "github.com/pulumi/pulumi-oci/sdk/go/oci/core" - "github.com/pulumi/pulumi-oci/sdk/go/oci/identity" - "github.com/pulumi/pulumi/sdk/v3/go/pulumi" - "github.com/pulumi/pulumi/sdk/v3/go/pulumi/config" -) - -// setupHostBeta provisions the beta (near-pre-production) instance. Unlike the -// main host it is not placed behind the load balancer: beta.happydomain.org -// points directly at this instance's public IP. It runs a more recent, -// manually-pinned happyDomain version with real users, hence its own restic -// backup repository. -func setupHostBeta(ctx *pulumi.Context, ocicfg *config.Config, compartment *identity.Compartment, subnet *core.Subnet) error { - cfg := config.New(ctx, "") - - // Get boot image - imageId := compartment.CompartmentId.ApplyT(func(id string) string { - images, _ := core.GetImages(ctx, &core.GetImagesArgs{ - CompartmentId: id, - OperatingSystem: pulumi.StringRef("Canonical Ubuntu"), - OperatingSystemVersion: pulumi.StringRef("24.04 Minimal"), - SortBy: pulumi.StringRef("TIMECREATED"), - SortOrder: pulumi.StringRef("DESC"), - Shape: pulumi.StringRef(SHAPE_AMD64), - }) - return images.Images[0].Id - }).(pulumi.StringOutput) - - // Get availability domains - availabilityDomainName := compartment.CompartmentId.ApplyT(func(id string) string { - availabilityDomains, _ := identity.GetAvailabilityDomains(ctx, &identity.GetAvailabilityDomainsArgs{ - CompartmentId: id, - }) - return availabilityDomains.AvailabilityDomains[0].Name - }).(pulumi.StringOutput) - - // Load cloudinit - userData, err := ioutil.ReadFile("cloud-init-beta.yaml") - if err != nil { - return err - } - - // Create an OCI instance - instance, err := core.NewInstance(ctx, "happydomain-beta-1", &core.InstanceArgs{ - AvailabilityDomain: availabilityDomainName, - CompartmentId: compartment.ID(), - DisplayName: pulumi.Sprintf("%s-happydomain-beta", ctx.Stack()), - Shape: pulumi.String(SHAPE_AMD64), - SourceDetails: &core.InstanceSourceDetailsArgs{ - SourceId: imageId, - SourceType: pulumi.String("image"), - }, - CreateVnicDetails: &core.InstanceCreateVnicDetailsArgs{ - AssignIpv6ip: pulumi.Bool(true), - SubnetId: subnet.ID(), - DisplayName: pulumi.Sprintf("%s-happydomain-beta", ctx.Stack()), - }, - ExtendedMetadata: pulumi.Map{ - "EMAIL_SMTP_HOST": pulumi.String("smtp.email." + cfg.Require("region_origin") + ".oci.oraclecloud.com"), - "EMAIL_SMTP_PORT": pulumi.String("587"), - "EMAIL_SMTP_USERNAME": cfg.RequireSecret("happydomain_smtp_user"), - "EMAIL_SMTP_PASSWORD": cfg.RequireSecret("happydomain_smtp_password"), - "HAPPYDOMAIN_JWT_SECRET_KEY": cfg.RequireSecret("happydomain_beta_jwt_secret_key"), - "HAPPYDOMAIN_OVH_APPLICATION_KEY": cfg.RequireSecret("happydomain_ovh_application_key"), - "HAPPYDOMAIN_OVH_APPLICATION_SECRET": cfg.RequireSecret("happydomain_ovh_application_secret"), - "HAPPYDOMAIN_VERSION": pulumi.String("latest"), - "MY_DOMAIN": pulumi.String("beta.happydomain.org"), - "RESTIC_REPOSITORY": pulumi.String("s3:blob.nemunai.re/zbackup-happydomain-beta"), - "RESTIC_PASSWORD": cfg.RequireSecret("restic_password"), - "RESTIC_AWS_ACCESS_KEY_ID": cfg.RequireSecret("restic_aws_access_key_id"), - "RESTIC_AWS_SECRET_ACCESS_KEY": cfg.RequireSecret("restic_aws_secret_access_key"), - }, - Metadata: pulumi.Map{ - "user_data": pulumi.String(base64.StdEncoding.EncodeToString(userData)), - "ssh_authorized_keys": pulumi.String(SSH_AUTHORIZED_KEYS), - }, - }) - if err != nil { - return err - } - - // Export the public IP so DNS for beta.happydomain.org can point at it - // (the IPv6 address is read off the VNIC from the OCI console, as for the - // main host). - ctx.Export("beta-instance-ip", instance.PublicIp) - - return nil -} diff --git a/main.go b/main.go index c4086a7..3e0b5a6 100644 --- a/main.go +++ b/main.go @@ -10,53 +10,33 @@ func main() { pulumi.Run(func(ctx *pulumi.Context) error { ocicfg := config.New(ctx, "oci") - if ocicfg.Require("region") == "uk-london-1" { - // My Compartment - compartment, err := identity.NewCompartment(ctx, "compartment", &identity.CompartmentArgs{ - Name: pulumi.Sprintf("%s-happydomain-compartment", ctx.Stack()), - Description: pulumi.String("Compartment for happyDomain"), - }) - if err != nil { - return err - } + // My Compartment + compartment, err := identity.NewCompartment(ctx, "compartment", &identity.CompartmentArgs{ + Name: pulumi.Sprintf("%s-happydomain-compartment", ctx.Stack()), + Description: pulumi.String("Compartment for happyDomain"), + }) + if err != nil { + return err + } - ns, listmonkAuthToken, err := setupListmonkStorage(ctx, ocicfg, compartment) - if err != nil { - return err - } + ns, listmonkAuthToken, err := setupListmonkStorage(ctx, ocicfg, compartment) + if err != nil { + return err + } - pemprvkey, smtpcreds, err := setupEmails(ctx, ocicfg, compartment) - if err != nil { - return err - } + pemprvkey, smtpcreds, err := setupEmails(ctx, ocicfg, compartment) + if err != nil { + return err + } - subnet, err := setupNetwork(ctx, compartment) - if err != nil { - return err - } + subnet, err := setupNetwork(ctx, compartment) + if err != nil { + return err + } - err = setupHostMain(ctx, ocicfg, compartment, ns, subnet, listmonkAuthToken, smtpcreds, pemprvkey) - if err != nil { - return err - } - } else if ocicfg.Require("region") == "eu-zurich-1" { - compartment, err := identity.NewCompartment(ctx, "compartment", &identity.CompartmentArgs{ - Name: pulumi.Sprintf("%s-happydomain-compartment", ctx.Stack()), - Description: pulumi.String("Compartment for happyDomain"), - }) - if err != nil { - return err - } - - subnet, err := setupNetwork(ctx, compartment) - if err != nil { - return err - } - - err = setupHostBeta(ctx, ocicfg, compartment, subnet) - if err != nil { - return err - } + err = setupHostMain(ctx, ocicfg, compartment, ns, subnet, listmonkAuthToken, smtpcreds, pemprvkey) + if err != nil { + return err } return nil