{"id":15415869,"url":"https://github.com/davidje13/website","last_synced_at":"2026-05-11T07:37:34.896Z","repository":{"id":151511310,"uuid":"157738539","full_name":"davidje13/Website","owner":"davidje13","description":"My website","archived":false,"fork":false,"pushed_at":"2023-10-19T19:12:07.000Z","size":152,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-20T13:21:10.614Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://www.davidje13.com","language":"Shell","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/davidje13.png","metadata":{"files":{"readme":"Readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-11-15T16:10:56.000Z","updated_at":"2024-04-25T06:21:19.000Z","dependencies_parsed_at":null,"dependency_job_id":"fb6727ea-7d1f-41cc-bfba-77e22a1e15b8","html_url":"https://github.com/davidje13/Website","commit_stats":{"total_commits":111,"total_committers":1,"mean_commits":111.0,"dds":0.0,"last_synced_commit":"6061402da6358d4f9da9686b7df9d13065bae799"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/davidje13/Website","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidje13%2FWebsite","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidje13%2FWebsite/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidje13%2FWebsite/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidje13%2FWebsite/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/davidje13","download_url":"https://codeload.github.com/davidje13/Website/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidje13%2FWebsite/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265645425,"owners_count":23804185,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-01T17:10:03.533Z","updated_at":"2026-05-11T07:37:29.843Z","avatar_url":"https://github.com/davidje13.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Website Setup Scripts\n\nThis script was used to build\n[davidje13.com](https://www.davidje13.com/).\n\nIt will install various subdomain code (and necessary environments)\nand install an nginx proxy server. It will also use the \"let's encrypt\"\nservice to get SSH keys for the site.\nSecurity updates will be applied automatically. Other updates can be\napplied by running:\n\n```sh\nsudo apt-get update;\nsudo apt-get dist-upgrade -y;\nsudo shutdown -r now;         # if needed\nsudo apt-get autoremove -y;\n```\n\nThe subdomain code will be refreshed automatically each day if changes\nare found.\n\nUpdates to this repository can be applied by re-running the\n`installer.sh` script.\n\n# AWS Instance\n\n## EC2\n\nUse an ED25519 key pair\n- for best security, generate a key locally:\n   ```sh\n   ssh-keygen -t ed25519 -N '' -C \"website\" -f ~/.ssh/website\n   ```\n- import the public key into AWS either via the UI\n  (Network \u0026 Security \u0026rarr; Key Pairs \u0026rarr; Actions \u0026rarr; Import Key Pair, copy contents of `website.pub` into box),\n  or via the CLI:\n  ```\n  aws ec2 import-key-pair --key-name \"website\" --public-key-material \"$(cat ~/.ssh/website.pub)\"\n  ```\n\nLaunch an instance with the following config:\n\n- AMI: `ami-090b049bea4780001` (Ubuntu 22.04, 64-bit, Arm)\n- Architecture: ARM\n- Instance Type: t4g.micro\n- Key pair: as created earlier\n- Use a security group which allows inbound traffic on:\n  - 80 (public: `0.0.0.0/0` \u0026 `::/0`)\n  - 443 (public: `0.0.0.0/0` \u0026 `::/0`)\n  - 22 (your ip)\n- Storage: 8GiB gp3\n  - Encryption enabled (KMS key can be left as default, using aws/ebs)\n  - IOPS: 3000\n  - Throughput: 125\n- Instance auto-recovery: Default\n- Termination protection: Enable\n- Credit specification: Standard\n\n```json\n{\n  \"MaxCount\": 1,\n  \"MinCount\": 1,\n  \"ImageId\": \"ami-090b049bea4780001\",\n  \"InstanceType\": \"t4g.micro\",\n  \"KeyName\": \"website\",\n  \"DisableApiTermination\": true,\n  \"EbsOptimized\": true,\n  \"BlockDeviceMappings\": [\n    {\n      \"DeviceName\": \"/dev/sda1\",\n      \"Ebs\": {\n        \"Encrypted\": true,\n        \"DeleteOnTermination\": true,\n        \"Iops\": 3000,\n        \"SnapshotId\": \"snap-05b63c7cce6fcdf1e\",\n        \"VolumeSize\": 8,\n        \"VolumeType\": \"gp3\",\n        \"Throughput\": 125\n      }\n    }\n  ],\n  \"NetworkInterfaces\": [\n    {\n      \"AssociatePublicIpAddress\": true,\n      \"DeviceIndex\": 0,\n      \"Groups\": [\"\u003cfill in\u003e\"]\n    }\n  ],\n  \"CreditSpecification\": {\n    \"CpuCredits\": \"standard\"\n  },\n  \"PrivateDnsNameOptions\": {\n    \"HostnameType\": \"ip-name\",\n    \"EnableResourceNameDnsARecord\": true,\n    \"EnableResourceNameDnsAAAARecord\": false\n  },\n  \"MaintenanceOptions\": {\n    \"AutoRecovery\": \"default\"\n  }\n}\n```\n\nAfter creation:\n\n- assign an elastic IP (this can be done after the install script completes waiting on DNS changes if migrating an existing deployment)\n- assign an IPv6 address (see below, from step 5 if IPv6 already configured for VPC)\n- Disable metadata (Actions \u0026rarr; Instance settings \u0026rarr; Modify instance metadata options)\n  Note: do not disable this when creating the instance, as it is required by AWS for configuring SSH keys.\n\n## CloudWatch\n\n- Restart if instance is down for 15 minutes\n  - No notification\n  - Action: \"Reboot\"\n  - Thresholds:\n    - Data: StatusCheckFailed: Instance\n    - Group: Maximum\n    - Period: 5 minutes\n    - Consecutive Periods: 3\n\n- Recover if system is down for 15 minutes\n  - No notification\n  - Action: \"Recover\"\n  - Thresholds:\n    - Data: StatusCheckFailed: System\n    - Group: Maximum\n    - Period: 5 minutes\n    - Consecutive Periods: 3\n\n## IPv6\n\nTo enable IPv6:\n\n1. Go to the default VPC configuration (or whichever VPC the instance is in):\n   1. Select \"Actions\" \u0026rarr; \"Edit CIDRs\"\n   2. Select \"Add new IPv6 CIDR\" and choose one of the options\n      (davidje13.com uses \"Amazon-provided\")\n2. Go to the subnet(s) your EC2 instance(s) are in. For each one:\n   1. Select \"Actions\" \u0026rarr; \"Edit IPv6 CIDRs\"\n   2. Select \"Add IPv6 CIDR\", and enter any available value for the block\n      (must be different for each subnet, and probably a good idea to start at `00` or `01`)\n   3. Save\n3. Still within the VPC section of AWS, go to the Route Table being used by the instance:\n   1. Select \"Actions\" \u0026rarr; \"Edit Routes\"\n   2. Add the route destination: `::/0`, target: \"Internet Gateway\"\n      (then select the same value already used for `0.0.0.0/0`)\n   3. Save\n4. Ensure the EC2 Security Group has been set up with `::/0` inbound rules, as described above.\n   Also ensure it has an outbound rule for all traffic to `::/0` (this will be auto-created by\n   the earlier steps, unless outbound rules have been customised)\n5. Go to the EC2 Instance\n   1. Select \"Actions\" \u0026rarr; \"Networking\" \u0026rarr; \"Manage IP addresses\"\n   2. Expand \"eth0\" and in the \"IPv6\" section choose \"Assign new IP address\"\n   3. Either enter a specific IP address (e.g. for migrating an existing deployment) or leave\n      the field blank to assign a random IP address within the subnet range\n   4. Select \"Assign primary IPv6 IP\"\n      (this will ensure the IP address does not change, allowing easier Route 53 config)\n   5. Save\n6. Note the assigned IPv6 address and add `AAAA` records to Route53 (see below)\n\nFull guide from AWS: \u003chttps://docs.aws.amazon.com/vpc/latest/userguide/vpc-migrate-ipv6.html\u003e\n\n## Route53\n\n(skip `AAAA` record if IPv6 has not been configured)\n\n| type  | name                | value                       | ttl    |\n|-------|---------------------|-----------------------------|--------|\n| A     | `\u003cdomain\u003e`          | `\u003celastic ip\u003e`              | 1 hour |\n| AAAA  | `\u003cdomain\u003e`          | `\u003cipv6\u003e`                    | 1 hour |\n| CNAME | `www.\u003cdomain\u003e`      | `\u003cdomain\u003e`                  | 7 days |\n| CNAME | `retro.\u003cdomain\u003e`    | `\u003cdomain\u003e`                  | 7 days |\n| CNAME | `retros.\u003cdomain\u003e`   | `\u003cdomain\u003e`                  | 7 days |\n| CNAME | `refacto.\u003cdomain\u003e`  | `\u003cdomain\u003e`                  | 7 days |\n| CNAME | `sequence.\u003cdomain\u003e` | `\u003cdomain\u003e`                  | 7 days |\n| CAA   | `\u003cdomain\u003e`          | `0 issue \"letsencrypt.org\"` | 7 days |\n\nIf the domain will not send email, the following should also be added:\n\n| type | name                    | value                              | ttl   |\n|------|-------------------------|------------------------------------|-------|\n| TXT  | `\u003cdomain\u003e`              | `v=spf1 -all`                      | 1 day |\n| TXT  | `*._domainkey.\u003cdomain\u003e` | `v=DKIM1;p=`                       | 1 day |\n| TXT  | `_dmarc.\u003cdomain\u003e`       | `v=DMARC1;p=reject;adkim=s;aspf=s` | 1 day |\n\n([source](https://www.cloudflare.com/learning/dns/dns-records/protect-domains-without-email/))\n\n## Installation\n\nOnce the EC2 \u0026 Route53 config is done, log in to the box:\n\n```sh\nssh -i ~/.ssh/website ubuntu@\u003cpublic-address\u003e\n```\n\nand run:\n\n```sh\ngit clone https://github.com/davidje13/Website.git\nWebsite/installer.sh\n# this will probably ask for a restart, or will eventually complain about not having a domain\nsudo shutdown -r now # SSH session will terminate - reconnect\n\ncp Website/env/refacto.template.env Website/env/refacto.env\n\nvi Website/env/refacto.env\n# fill in any appropriate options then save\n\nWebsite/installer.sh '\u003cdomain\u003e'\n```\n\nThe script will automatically wait for DNS records to be configured when\nneeded, so you do not have to set up the DNS before running the script.\n\n## Backup and restore\n\nYou can backup and restore the Refacto database using the commands:\n\n```sh\nWebsite/refacto/backup.sh # generates backup-*.tar.gz\n```\n\n```sh\n# restore from backup-2020-10-03T12-00-00.tar.gz\nWebsite/refacto/restore.sh backup-2020-10-03T12-00-00.tar.gz\n```\n\nThere is also an option to restore data from a backup file during\ninstallation.\n\n## Migrating\n\nWhen migrating from an old server, downtime can be minimised by waiting until\nthe new server requests a backup file to load before shutting down and backing\nup the old server:\n\n1. Begin deployment of new server (follow steps above) until prompted with:\n   \"Enter filename to import refacto data from\"\n2. On old server, run:\n   ```sh\n   sudo systemctl stop refacto4080.service\n   sudo systemctl stop refacto4081.service\n   Website/refacto/backup.sh\n   ```\n3. Copy the generated backup file to the new server\n4. Enter the filename in the prompt\n5. Wait for the script to prompt:\n   \"Created background task waiting for (domain) DNS to point to this instance\"\n6. Reassign the elastic IPv4, and update the AAAA DNS entry to point to the new\n   instance's IPv6.\n   _Note: this will cause SSH sessions to end if they are using IPv4_\n7. Installation should complete automatically.\n\n## Checking logs\n\nServices store logs in:\n\n- `/var/www/sequence/logs/log*/*`\n- `/var/www/refacto/logs/log*/*`\n- `/var/log/nginx/*`\n\nSequence and Refacto use `multilog`'s `tai64n` format for timestamps.\nThese are not human-readable, but can be viewed with:\n\n```sh\ntai64nlocal \u003c \"my-log-file-here\" | less\n```\n\nFor example to see how often sequence diagram's render API is called:\n\n```sh\ncat /var/www/sequence/logs/log*/{*.s,current} | grep RENDER | sort\n```\n\nOld logs are `gzip`'ed. These can be viewed with:\n\n```sh\ngunzip -c \"my-old-log-file-here.gz\" | less\n```\n\nTo view all recent nginx error logs:\n\n```sh\n( cat /var/log/nginx/error.log /var/log/nginx/error.log.1; gunzip -c /var/log/nginx/error.log.*.gz ) \\\n| sort | cut -d' ' -f1,2,5- | less\n```\n\nTo view all recent nginx access logs:\n\n```sh\n( cat /var/log/nginx/access.log /var/log/nginx/access.log.1; gunzip -c /var/log/nginx/access.log.*.gz ) \\\n| awk '{ print $4 \" \" $5 \" \" $1 \" \" substr($0, length($1 $2 $3 $4 $5) + 6) }' | sort | less\n```\n\nTo view current firewall stats (e.g. number of packets to particular ports):\n\n```sh\nsudo nft list table inet filter\n```\n\nTo view packets sent to unknown ports:\n\n```sh\ngrep ' kernel:' \u003c /var/log/syslog\n```\n\n## Post Setup\n\nYou should add the root domain to the\n[HSTS preload list](https://hstspreload.org)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdavidje13%2Fwebsite","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdavidje13%2Fwebsite","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdavidje13%2Fwebsite/lists"}