diff --git a/404.html b/404.html index 03178f590..9a2c0d24b 100644 --- a/404.html +++ b/404.html @@ -17,17 +17,17 @@ 404 Page not found :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/index.html b/index.html index 6894bca5c..37127e42f 100644 --- a/index.html +++ b/index.html @@ -29,17 +29,17 @@ book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/index.search.js b/index.search.js index 4b2b8ec0b..b9f2028d1 100644 --- a/index.search.js +++ b/index.search.js @@ -177,7 +177,7 @@ var relearn_search_index = [ }, { "breadcrumb": "book.rymcg.tech", - "content": " This book serves as your guide to installing Docker on a small portable Linux device (e.g., Raspberry Pi) and deploying some web service containers on it.\nYou’ll also create and configure a public cloud server (e.g., a DigitalOcean droplet) whose sole purpose is to host a VPN (WireGuard) and public gateway (Traefik), enabling the Raspberry Pi to securely connect from any location.\nThrough the encrypted tunnel established by this connection, the Pi can publish services to the Internet even when operating behind a restrictive firewall, such as public Wi-Fi, mobile hotspots, or carrier-grade NAT. As long as you can get unblocked outgoing Internet access, you can self-host a roaming public server from anywhere!\nd.rymcg.tech Chat with us on Matrix Index Acknowledgements Introduction Set up DNS Register a domain name Add the domain to DigitalOcean DNS Generate DigitalOcean API token for ACME challenge Set up Raspberry Pi Build your Raspberry Pi Install Raspberry Pi OS Set up networking Set up SSH Install Docker Install d.rymcg.tech Install Traefik Install Whoami Set up sentry Droplet Launch DigitalOcean droplet Configure the sentry context on the Pi Configure d.rymcg.tech for the sentry Configure WireGuard VPN Configure sentry wireguard server Configure Raspberry Pi WireGuard client Set up public SSH Install core services Forgejo Traefik-Forward-Auth (sentry authorization) Install apps Immich SFTP (and Thttpd) MinIO S3 (and Filestash) Homepage Yourls Nginx and PHP Jupyterlab Maintainence Native Backup Upgrade Troubleshooting ", + "content": " This book serves as your guide to installing Docker on a small portable Linux device (e.g., Raspberry Pi) and deploying some web service containers on it.\nYou’ll also create and configure a public cloud server (e.g., a DigitalOcean droplet) whose sole purpose is to host a VPN (WireGuard) and public gateway (Traefik), enabling the Raspberry Pi to securely connect from any location.\nThrough the encrypted tunnel established by this connection, the Pi can publish services to the Internet even when operating behind a restrictive firewall, such as public Wi-Fi, mobile hotspots, or carrier-grade NAT. As long as you can get unblocked outgoing Internet access, you can self-host a roaming public server from anywhere!\nd.rymcg.tech Chat with us on Matrix Index Acknowledgements Introduction Set up DNS Register a domain name Add the domain to DigitalOcean DNS Generate DigitalOcean API token for ACME challenge Set up Raspberry Pi Build your Raspberry Pi Install Raspberry Pi OS Set up networking Set up SSH Install Docker Install d.rymcg.tech Install Traefik Install Whoami Set up sentry Droplet Launch DigitalOcean droplet Configure the sentry context on the Pi Configure d.rymcg.tech for the sentry Configure WireGuard VPN Configure sentry wireguard server Configure Raspberry Pi WireGuard client Set up public SSH Install core services Forgejo Traefik-Forward-Auth (sentry authorization) Postfix-Relay (MTA) Install apps Immich SFTP (and Thttpd) MinIO S3 (and Filestash) Homepage Yourls Nginx and PHP Jupyterlab Maintainence Native Backup Upgrade Troubleshooting ", "description": "This book serves as your guide to installing Docker on a small portable Linux device (e.g., Raspberry Pi) and deploying some web service containers on it.\nYou’ll also create and configure a public cloud server (e.g., a DigitalOcean droplet) whose sole purpose is to host a VPN (WireGuard) and public gateway (Traefik), enabling the Raspberry Pi to securely connect from any location.\nThrough the encrypted tunnel established by this connection, the Pi can publish services to the Internet even when operating behind a restrictive firewall, such as public Wi-Fi, mobile hotspots, or carrier-grade NAT.", "tags": [], "title": "Portable Docker: Build and Deploy Anywhere with WireGuard Tunneling", @@ -249,8 +249,8 @@ var relearn_search_index = [ }, { "breadcrumb": "book.rymcg.tech \u003e Portable Docker", - "content": " There are a few services you should consider installing before any others, which we will call core services:\nIndex Forgejo Traefik-Forward-Auth (sentry authorization) ", - "description": " There are a few services you should consider installing before any others, which we will call core services:\nIndex Forgejo Traefik-Forward-Auth (sentry authorization) ", + "content": " There are a few services you should consider installing before any others, which we will call core services:\nIndex Forgejo Traefik-Forward-Auth (sentry authorization) Postfix-Relay (MTA) ", + "description": " There are a few services you should consider installing before any others, which we will call core services:\nIndex Forgejo Traefik-Forward-Auth (sentry authorization) Postfix-Relay (MTA) ", "tags": [], "title": "Install core services", "uri": "/portable-docker/install-core-services/index.html" @@ -265,12 +265,20 @@ var relearn_search_index = [ }, { "breadcrumb": "book.rymcg.tech \u003e Portable Docker \u003e Install core services", - "content": "Sentry authorization Some apps may already have their own authentication mechanisms, while others may not. Sentry authorization creates a common authentication and authorization framework in front of your applications via Traefik middleware. Sentry authorization happens before any existing auth mechanisms in the app itself, and so it acts as a front door gatekeeper for your apps. It can’t control what users are allowed to do once they get in, but it does control who is allowed in through the front door.\nUsers are authenticated via the Forgejo instance and traefik-forward-auth. Users are authorized by a group membership filter applied on a per-app basis. Configure traefik-forward-auth Run this on the Raspberry Pi pi make traefik-forward-auth config (stdout) TRAEFIK_FORWARD_AUTH_HOST: Enter the traefik-foward-auth host domain name (eg. auth.example.com) : auth.pi.example.com TRAEFIK_FORWARD_AUTH_COOKIE_DOMAIN: Enter the cookie domain name (ie ROOT domain) (eg. example.com) : pi.example.com ? Select the OAuth provider to use \u003e gitea github google discord TRAEFIK_FORWARD_AUTH_GITEA_DOMAIN: Enter your gitea domain name (eg. git.example.com) : git.pi.example.com At this point it will open w3m to the gitea instance asking you to sign in. Because this isn’t very user friendly, so just press q and then y to quit w3m.\nOpen your preffered web browser and open up the gitea URL: https://git.pi.example.com Make sure you are logged in as the root user. Open the root user settings page, click Applications. Fill in the section titled Manage OAuth2 applications: Enter an application name as a public identifier. Enter the redirect URI https:://auth.pi.example.com/_oauth. Click Create Application. This will show you the OAuth2 client ID and secret: Back in your terminal session, it should be asking you to fill these same details in:\n(stdout) TRAEFIK_FORWARD_AUTH_PROVIDERS_GENERIC_OAUTH_CLIENT_ID: Copy and Paste the OAuth2 client ID here : 38d6c7f7-c712-43a9-967c-27888819e85f TRAEFIK_FORWARD_AUTH_PROVIDERS_GENERIC_OAUTH_CLIENT_SECRET: Copy and Paste the OAuth2 client secret here : gto_4g54tazy7oyslypqhr7z7khundcmtwezlkdeyghe7ctj7k4gltvq TRAEFIK_FORWARD_AUTH_LOGOUT_REDIRECT: Enter the logout redirect URL : https://git.pi.example.com/logout Install Traefik-Forward-Auth Run this on the Raspberry Pi pi make traefik-forward-auth install Add a new route on the sentry (droplet) Run this on the Raspberry Pi sentry make traefik config (stdout) ? Traefik: \u003e Config Install (make install) Admin Exit (ESC) ? Traefik Configuration: ^ Entrypoints (including dashboard) TLS certificates and authorities Middleware (including sentry auth) \u003e Advanced Routing (Layer 7 / Layer 4 / WireGuard) Error page template Logging level Access logs ? Traefik routes \u003e Configure layer 7 TLS proxy Configure layer 4 TCP/UDP proxy Configure wireguard VPN ? Layer 7 TLS Proxy: List layer 7 ingress routes \u003e Add new layer 7 ingress route Remove layer 7 ingress routes Disable layer 7 TLS Proxy Enter the public domain (SNI) for the route: : auth.pi.example.com Enter the destination IP address to forward to: : 10.13.16.2 Enter the destination TCP port to forward to: : 443 \u003e Do you want to enable Proxy Protocol for this route? Yes ## Layer 7 TLS Proxy is ENABLED. ## Configured Layer 7 Routes: Entrypoint Destination_address Destination_port Proxy_protocol ---------- ------------------- ---------------- -------------- auth.pi.example.com 10.13.16.2 443 2 Press ESC three times to go back to the main menu, and re-install Traefik:\n(stdout) ? Traefik: Config \u003e Install (make install) Admin Exit (ESC) After installation, press ESC to quit the config tool.\nAdd user groups for sentry authorization With OAuth2 sentry authorization enabled, users are authorized to access apps only if they are a member of an authorized group for that app. You need to create the group membership lists in the Traefik config:\nRun this on the Raspberry Pi pi make traefik config (stdout) ? Traefik: \u003e Config Install (make install) Admin Exit (ESC) ? Traefik Configuration: Traefik user Entrypoints (including dashboard) TLS certificates and authorities \u003e Middleware (including sentry auth) Advanced Routing (Layer 7 / Layer 4 / Wireguard) Error page template v Logging level ? Traefik middleware config: MaxMind geoIP locator \u003e OAuth2 sentry authorization (make sentry) ? Sentry Authorization Manager (main menu): \u003e Group Manager User Manager List all members List authorized callback URLs Quit \u003e Sentry Authorization Manager (main menu): Group Manager ? Choose a group to manage \u003e Create a new group ? Enter the name of the group to create: admin \u003e Do you want to add users to this group now? Yes Enter the new user id(s) to add, one per line: ? Enter a user ID (Press Esc or enter a blank value to finish) me@example.com Tip Replace me@example.com with the same email address that you used to sign up for your personal account in Forgejo. You can add more users to the group if you wish, when done enter a blank line.\nRe-configure whoami with sentry authorization (OAuth2) Run this on the Raspberry Pi pi make whoami config (stdout) WHOAMI_TRAEFIK_HOST: Enter the whoami domain name (eg. whoami.example.com) : whoami.pi.example.com ? Do you want to enable sentry authorization in front of this app (effectively making the entire site private)? No Yes, with HTTP Basic Authentication \u003e Yes, with Oauth2 Yes, with Mutual TLS (mTLS) ? Which authorization group do you want to permit access to this app? \u003e admin Tip This will allow only the admin authorization group to access this instance.\nRemember, you can create extra authorization groups in the Traefik config, that way you can have separate user access per instance.\nRe-install whoami:\nRun this on the Raspberry Pi pi make whoami install Test login for whoami Open the whoami app in your web browser: https://whoami.pi.example.com.\nYou should be automatically redirected to the Foregjo app to login.\nThe first time a Forgejo user authenticates to a sentry authorization protected app, they should see this prompt:\nConfirm by clicking the button Authorize Application.\nIf the user is authorized, they should be automatically redirected back to the whoami app.\nThe output of whoami now reflects the authorized user:\n(stdout) Name: default Hostname: c863ccd86cec IP: 127.0.0.1 IP: ::1 IP: 172.19.0.2 RemoteAddr: 172.19.0.1:38606 GET / HTTP/1.1 Host: whoami.pi.example.com User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:127.0) Gecko/20100101 Firefox/127.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 Accept-Encoding: gzip, deflate, br, zstd Accept-Language: en-US,en;q=0.5 Cookie: _forward_auth=xxxxxxxxxxxxxxxxxxxxxxxxxxx=|123456789|me@example.com Dnt: 1 Priority: u=1 Sec-Fetch-Dest: document Sec-Fetch-Mode: navigate Sec-Fetch-Site: same-site Sec-Fetch-User: ?1 Te: trailers Upgrade-Insecure-Requests: 1 X-Forwarded-For: 192.168.1.1 X-Forwarded-Host: whoami.pi.example.com X-Forwarded-Port: 443 X-Forwarded-Proto: https X-Forwarded-Server: pi X-Forwarded-User: me@example.com X-Real-Ip: 192.168.1.1 The request shows the new details:\nCookie the cookie value is set by the traefik-forward-auth middleware once the user is successfully authenticated. The X-Forwarded-User is passed to the application to identify the validated user id (email address). Reconfigure other apps to use OAuth2 All other apps may be protected with sentry authorization in the same manner as whoami.\nNext steps Install apps. ", + "content": "Sentry authorization Some apps may already have their own authentication mechanisms, while others may not. Sentry authorization creates a common authentication and authorization framework in front of your applications via Traefik middleware. Sentry authorization happens before any existing auth mechanisms in the app itself, and so it acts as a front door gatekeeper for your apps. It can’t control what users are allowed to do once they get in, but it does control who is allowed in through the front door.\nUsers are authenticated via the Forgejo instance and traefik-forward-auth. Users are authorized by a group membership filter applied on a per-app basis. Configure traefik-forward-auth Run this on the Raspberry Pi pi make traefik-forward-auth config (stdout) TRAEFIK_FORWARD_AUTH_HOST: Enter the traefik-foward-auth host domain name (eg. auth.example.com) : auth.pi.example.com TRAEFIK_FORWARD_AUTH_COOKIE_DOMAIN: Enter the cookie domain name (ie ROOT domain) (eg. example.com) : pi.example.com ? Select the OAuth provider to use \u003e gitea github google discord TRAEFIK_FORWARD_AUTH_GITEA_DOMAIN: Enter your gitea domain name (eg. git.example.com) : git.pi.example.com At this point it will open w3m to the gitea instance asking you to sign in. Because this isn’t very user friendly, so just press q and then y to quit w3m.\nOpen your preffered web browser and open up the gitea URL: https://git.pi.example.com Make sure you are logged in as the root user. Open the root user settings page, click Applications. Fill in the section titled Manage OAuth2 applications: Enter an application name as a public identifier. Enter the redirect URI https:://auth.pi.example.com/_oauth. Click Create Application. This will show you the OAuth2 client ID and secret: Back in your terminal session, it should be asking you to fill these same details in:\n(stdout) TRAEFIK_FORWARD_AUTH_PROVIDERS_GENERIC_OAUTH_CLIENT_ID: Copy and Paste the OAuth2 client ID here : 38d6c7f7-c712-43a9-967c-27888819e85f TRAEFIK_FORWARD_AUTH_PROVIDERS_GENERIC_OAUTH_CLIENT_SECRET: Copy and Paste the OAuth2 client secret here : gto_4g54tazy7oyslypqhr7z7khundcmtwezlkdeyghe7ctj7k4gltvq TRAEFIK_FORWARD_AUTH_LOGOUT_REDIRECT: Enter the logout redirect URL : https://git.pi.example.com/logout Install Traefik-Forward-Auth Run this on the Raspberry Pi pi make traefik-forward-auth install Add a new route on the sentry (droplet) Run this on the Raspberry Pi sentry make traefik config (stdout) ? Traefik: \u003e Config Install (make install) Admin Exit (ESC) ? Traefik Configuration: ^ Entrypoints (including dashboard) TLS certificates and authorities Middleware (including sentry auth) \u003e Advanced Routing (Layer 7 / Layer 4 / WireGuard) Error page template Logging level Access logs ? Traefik routes \u003e Configure layer 7 TLS proxy Configure layer 4 TCP/UDP proxy Configure wireguard VPN ? Layer 7 TLS Proxy: List layer 7 ingress routes \u003e Add new layer 7 ingress route Remove layer 7 ingress routes Disable layer 7 TLS Proxy Enter the public domain (SNI) for the route: : auth.pi.example.com Enter the destination IP address to forward to: : 10.13.16.2 Enter the destination TCP port to forward to: : 443 \u003e Do you want to enable Proxy Protocol for this route? Yes ## Layer 7 TLS Proxy is ENABLED. ## Configured Layer 7 Routes: Entrypoint Destination_address Destination_port Proxy_protocol ---------- ------------------- ---------------- -------------- auth.pi.example.com 10.13.16.2 443 2 Press ESC three times to go back to the main menu, and re-install Traefik:\n(stdout) ? Traefik: Config \u003e Install (make install) Admin Exit (ESC) After installation, press ESC to quit the config tool.\nAdd user groups for sentry authorization With OAuth2 sentry authorization enabled, users are authorized to access apps only if they are a member of an authorized group for that app. You need to create the group membership lists in the Traefik config:\nRun this on the Raspberry Pi pi make traefik config (stdout) ? Traefik: \u003e Config Install (make install) Admin Exit (ESC) ? Traefik Configuration: Traefik user Entrypoints (including dashboard) TLS certificates and authorities \u003e Middleware (including sentry auth) Advanced Routing (Layer 7 / Layer 4 / Wireguard) Error page template v Logging level ? Traefik middleware config: MaxMind geoIP locator \u003e OAuth2 sentry authorization (make sentry) ? Sentry Authorization Manager (main menu): \u003e Group Manager User Manager List all members List authorized callback URLs Quit \u003e Sentry Authorization Manager (main menu): Group Manager ? Choose a group to manage \u003e Create a new group ? Enter the name of the group to create: admin \u003e Do you want to add users to this group now? Yes Enter the new user id(s) to add, one per line: ? Enter a user ID (Press Esc or enter a blank value to finish) me@example.com Tip Replace me@example.com with the same email address that you used to sign up for your personal account in Forgejo. You can add more users to the group if you wish, when done enter a blank line.\nRe-configure whoami with sentry authorization (OAuth2) Run this on the Raspberry Pi pi make whoami config (stdout) WHOAMI_TRAEFIK_HOST: Enter the whoami domain name (eg. whoami.example.com) : whoami.pi.example.com ? Do you want to enable sentry authorization in front of this app (effectively making the entire site private)? No Yes, with HTTP Basic Authentication \u003e Yes, with Oauth2 Yes, with Mutual TLS (mTLS) ? Which authorization group do you want to permit access to this app? \u003e admin Tip This will allow only the admin authorization group to access this instance.\nRemember, you can create extra authorization groups in the Traefik config, that way you can have separate user access per instance.\nRe-install whoami:\nRun this on the Raspberry Pi pi make whoami install Test login for whoami Open the whoami app in your web browser: https://whoami.pi.example.com.\nYou should be automatically redirected to the Foregjo app to login.\nThe first time a Forgejo user authenticates to a sentry authorization protected app, they should see this prompt:\nConfirm by clicking the button Authorize Application.\nIf the user is authorized, they should be automatically redirected back to the whoami app.\nThe output of whoami now reflects the authorized user:\n(stdout) Name: default Hostname: c863ccd86cec IP: 127.0.0.1 IP: ::1 IP: 172.19.0.2 RemoteAddr: 172.19.0.1:38606 GET / HTTP/1.1 Host: whoami.pi.example.com User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:127.0) Gecko/20100101 Firefox/127.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 Accept-Encoding: gzip, deflate, br, zstd Accept-Language: en-US,en;q=0.5 Cookie: _forward_auth=xxxxxxxxxxxxxxxxxxxxxxxxxxx=|123456789|me@example.com Dnt: 1 Priority: u=1 Sec-Fetch-Dest: document Sec-Fetch-Mode: navigate Sec-Fetch-Site: same-site Sec-Fetch-User: ?1 Te: trailers Upgrade-Insecure-Requests: 1 X-Forwarded-For: 192.168.1.1 X-Forwarded-Host: whoami.pi.example.com X-Forwarded-Port: 443 X-Forwarded-Proto: https X-Forwarded-Server: pi X-Forwarded-User: me@example.com X-Real-Ip: 192.168.1.1 The request shows the new details:\nCookie the cookie value is set by the traefik-forward-auth middleware once the user is successfully authenticated. The X-Forwarded-User is passed to the application to identify the validated user id (email address). Reconfigure other apps to use OAuth2 All other apps may be protected with sentry authorization in the same manner as whoami.", "description": "Sentry authorization Some apps may already have their own authentication mechanisms, while others may not. Sentry authorization creates a common authentication and authorization framework in front of your applications via Traefik middleware. Sentry authorization happens before any existing auth mechanisms in the app itself, and so it acts as a front door gatekeeper for your apps. It can’t control what users are allowed to do once they get in, but it does control who is allowed in through the front door.", "tags": [], "title": "Traefik-Forward-Auth (sentry authorization)", "uri": "/portable-docker/install-core-services/traefik-forward-auth/index.html" }, + { + "breadcrumb": "book.rymcg.tech \u003e Portable Docker \u003e Install core services", + "content": "Many apps require to send email for various purposes. Rather than configure each such container with your secret mail credentials, you can configure a single central mail forwarding service with postfix-relay.\n--- title: Authorized container networks may bridge with the Postfix-Relay to send outgoing email. --- graph TD; subgraph Docker network A[Container A] --\u0026gt;|private mail-only network| D[Postfix-Relay] B[Container B] --\u0026gt;|private mail-only network| D[Postfix-Relay] C[Container C] -.- F[Blocked] end D --\u0026gt;|Internet| E[Public SMTP server] E --\u0026gt; G[Allowed Email recipient] E --\u0026gt; H[Allowed Email recipient] E -.- I[Blocked Email recipient] Register the upstream SMTP service You will need access to a public email (SMTP) service for outgoing mail. Gather the following information from your provider:\nThe SMTP server domain, e.g., mail.example.com. The port, e.g., 465 (TLS) or 587 (STARTTLS). The username, e.g., me@example.com. The password, e.g., hunter2. Configure Postfix-Relay Run this on your Raspberry Pi pi make postfix-relay config Enter the domain name for this postfix instance:\n(stdout) POSTFIX_RELAY_TRAEFIK_HOST: Enter the domain name for this instance : smtp.d.example.com Enter the upstream SMTP server connection details:\n(stdout) POSTFIX_RELAY_RELAYHOST: Enter the outgoing SMTP server domain:port (eg. smtp.example.com:587) : mail.example.com:465 POSTFIX_RELAY_RELAYHOST_USERNAME: Enter the outgoing SMTP server username : username@example.com POSTFIX_RELAY_RELAYHOST_PASSWORD: Enter the outgoing SMTP server password : xxxxxxxxxxxxxxxxxxxx Select which network subdomains should be masked at the root domain (this is optional, and can be used to hide private subdomains from the email headers):\n(stdout) POSTFIX_RELAY_MASQUERADED_DOMAINS: Enter the root domains (separated by space) that should mask its sub-domains : example.com example.org Install Run this on your Raspberry Pi pi make postfix-relay install Test sending mail Run this on your Raspberry Pi ( RECIPIENT=\"recipient@example.com\" SENDER=\"root@localhost\" SUBJECT=\"Test Email\" BODY=\"This is a test email sent from Docker.\" docker run --rm \\ --network postfix-relay_default \\ -e RECIPIENT=\"$RECIPIENT\" \\ -e SENDER=\"$SENDER\" \\ -e SUBJECT=\"$SUBJECT\" \\ -e BODY=\"$BODY\" \\ alpine sh -c 'apk add --no-cache msmtp \u0026\u0026 \\ echo -e \"Subject: $SUBJECT\\n\\n$BODY\" | \\ msmtp --from=\"$SENDER\" \\ --host=postfix-relay-postfix-relay-1 \\ --port=587 \\ --tls=off \\ --tls-starttls=off \\ \"$RECIPIENT\" \u0026\u0026 \\ echo \"Email sent\" || \\ echo \"Email failed to send\"' ) Next steps Install apps. ", + "description": "Many apps require to send email for various purposes. Rather than configure each such container with your secret mail credentials, you can configure a single central mail forwarding service with postfix-relay.\n--- title: Authorized container networks may bridge with the Postfix-Relay to send outgoing email. --- graph TD; subgraph Docker network A[Container A] --\u0026gt;|private mail-only network| D[Postfix-Relay] B[Container B] --\u0026gt;|private mail-only network| D[Postfix-Relay] C[Container C] -.- F[Blocked] end D --\u0026gt;|Internet| E[Public SMTP server] E --\u0026gt; G[Allowed Email recipient] E --\u0026gt; H[Allowed Email recipient] E -.", + "tags": [], + "title": "Postfix-Relay (MTA)", + "uri": "/portable-docker/install-core-services/postfix-relay/index.html" + }, { "breadcrumb": "book.rymcg.tech", "content": "This book describes how this site is written, in Org-mode, with ox-hugo, and bits of Literate Programming.\nIndex Dependencies Building locally Publishing with GitHub pages Publishing with SFTP Using Org-mode and Emacs Navigating Org-mode files Editing Org-mode files Example Org / Hugo content Example Org Blocks Example Shortcodes Example of a deeply … Nested … Sub-chapter 1 Sub-chapter 2 Sub-chapter 3 ", @@ -745,7 +753,7 @@ var relearn_search_index = [ }, { "breadcrumb": "book.rymcg.tech \u003e Portable Docker \u003e Maintainence", - "content": "Backup of native machines is much harder than for virtual machines, that’s just the way it goes. With VMs, your hypervisor should have a builtin backup feature which can suspend (pause) the entire machine, make a snapshot of the disk and the entire RAM contents, resume the machine, and continue backing up the snapshot in the background. If you have the luxury of running your server as a VM (e.g., Proxmox PVE, or any cloud provider), it makes backups so much easier.\nWhen running Docker natively on a Raspberry Pi, you do not have that option. This chapter deals with the more intricate procedure of the backup of a non-virtual machine.\nRestic Restic is a modern open source backup tool, which has many great features including incremental backups, encryption, and offsite upload. It can maintain backups of huge sizes, and it only needs to upload the changes since the last backup.\nOne of the best ways to install Restic is with the script found on this blog post:\nDaily backups to S3 with Restic and systemd timers\nWarning The only problem with backing up files this way is that with containers that are always running, you need to make sure that the files are flushed to disk before the backup starts, otherwise your backup could become corrupted. For files that are only written to once (photos, videos, etc.) this might not be such a big deal, but for files that are constantly changing (e.g., databases) this is a problem.\nTip Evaluating this Restic script:\nPros:\nIt’s a self contained script not dependent on Docker. It can backup several directories and upload to an offsite S3 bucket. Point the script at any directory and it will make a backup of it (e.g., /home/pi/, /var/lib/docker/volumes [see Cons].) It supports a space-efficient incremental backup strategy. It’s a good option for backup of home directories and large media folders. Cons:\nNo integration with Docker; it cannot shutdown containers before backup. Backup of /var/lib/docker/volumes is not 100% safe. Files that are modified during the backup may become corrupted. Restoration requires the original script and for you to re-install Restic. Backup-Volume Backup-Volume is another backup tool that is specifically configured to backup Docker volumes and uploading archives to offsite storage (S3, SSH, DropBox).\nBackup-Volume can only handle complete backups (no incremental storage). For small datasets this is ideal, because each backup gets stored in a separate backup-XXXX.tar.gz, and its easy to restore with one file. For larger datasets, the duplication of backup files would be prohibitively expensive/wasteful (although you can tune the retention and pruning parameters to save some space, it won’t compare to the efficiency of Restic).\nBackup-Volume has a trick it can use in its favor: it can automatically stop and start containers before and after the backup runs. This makes this style of backup much safer for write intensive volumes (e.g., databases) and ensures that the data gets flushed before the backup starts.\nTip Evaluating Backup-Volume:\nPros:\nSpecifically designed to backup Docker volumes on a cron-like schedule. Manages the lifecycle of the containers to shut them down before a backup starts and to restart them afterward. Each backup is contained in a single file (backup-XXXX.tar.gz) which is uploaded to your S3 provider. Restoration is easy, just download the latest tarball and extract it. Automatic pruning of old archives helps to save some space. Cons:\nNo incremental backup support. Each backup duplicates the entire dataset. Ill-suited for large datasets. Setup Backup-Volume Prepare an S3 bucket offsite You may want to use your own minio S3 service (preferably installed on a separate offsite server), or a third party provider (AWS S3, DigitalOcean Spaces, Wasabi, etc.)\nYou will need to provide the S3 bucket and credentials that the backup process will use when uploading archives:\nS3 Endpoint domain. e.g., s3.example.com. S3 bucket name. e.g., test S3 access key id. e.g., test. S3 secret key. e.g., xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx. Configure Backup-Volume Run this on your Raspberry Pi ## Configures the default backup-volume instance:\u0001 pi make backup-volume config Select multiple existing volumes to backup together as one archive:\n(stdout) ? Select all the volumes to backup \u003e [x] test1_data [ ] forgejo_data [x] icecast_config [ ] icecast_logs [ ] mosquitto_mosquitto [ ] traefik_geoip_database v [ ] traefik_traefik Choose the backup schedule in cron format :\n(stdout) BACKUP_CRON_EXPRESSION: Enter the cron expression (eg. @daily) : @every 24h Tip Other example schedules:\n@every 1h15m @daily @weekly See more in the .env-dist file Choose the retention length (number of days) to keep backup archives before automatic pruning happens:\n(stdout) BACKUP_RETENTION_DAYS: Rotate backups older than how many days? (eg. 30) : 30 You can choose any of the supported storage mechanisms. For demo purposes, choose S3:\n(stdout) \u003e Which remote storage do you want to use? s3 BACKUP_AWS_ENDPOINT: Enter the S3 endpoint (e.g., s3.example.com) : s3.d.example.com BACKUP_AWS_S3_BUCKET_NAME: Enter the S3 bucket name (e.g., my-bucket) : backup-test-1 BACKUP_AWS_ACCESS_KEY_ID: Enter the S3 access key id (e.g., my-access-key) : backup-test-1 BACKUP_AWS_SECRET_ACCESS_KEY: Enter the S3 secret access key : OEuL3lMSdvdoFyVjEQTM4Trj/7VhHq7Q7cOFEpQPuxMHxsTVK3Hxne7st6Ty BACKUP_AWS_S3_PATH: Choose a directory inside the bucket (blank for root) : Tip You should use a dedicated bucket for each backup instance, or you can share the same bucket between several instances, as long as you are careful to configure a unique BACKUP_AWS_S3_PATH bucket sub-directory for each instance.\nYou may optionally preserve an additional copy of the archive in a local volume:\n(stdout) \u003e Do you want to keep a local backup in addition to the remote one? No Install Run this on your Raspberry Pi ## installs the default backup instance: pi make backup-volume install Instances All volume selections will backup to the same archive on the same schedule. To back up different volumes on different schedules, you should create more than one instance of Backup-Volume to create separate configs:\nRun this on your Raspberry Pi ## Creates a new backup instance named test: pi make backup-volume instance instance=test pi make backup-volume install instance=test Verify backup schedule Run this on your Raspberry Pi pi make backup-volume logs (stdout) backup-1 | 2024-10-16T02:37:00.263838944Z time=2024-10-16T02:37:00.262Z level=INFO msg=\"Successfully scheduled backup from environment with expression @daily\" backup-1 | 2024-10-16T02:37:00.266773318Z time=2024-10-16T02:37:00.266Z level=INFO msg=\"The backup will start at 12:00 AM\" Tip You should see a plain text log message describing when the backup will occur (The backup will start at 12:00 AM), except it will be ommitted if you use the @every syntax.\nRestore To restore a volume from a backup, simply untar the archive into the appropriate directory under /var/lib/docker/volumes.\nNotifications TODO", + "content": "Backup of native machines is much harder than for virtual machines, that’s just the way it goes. With VMs, your hypervisor should have a builtin backup feature which can suspend (pause) the entire machine, make a snapshot of the disk and the entire RAM contents, resume the machine, and continue backing up the snapshot in the background. If you have the luxury of running your server as a VM (e.g., Proxmox PVE, or any cloud provider), it makes backups so much easier.\nWhen running Docker natively on a Raspberry Pi, you do not have that option. This chapter deals with the more intricate procedure of the backup of a non-virtual machine.\nRestic Restic is a modern open source backup tool, which has many great features including incremental backups, encryption, and offsite upload. It can maintain backups of huge sizes, and it only needs to upload the changes since the last backup.\nOne of the best ways to install Restic is with the script found on this blog post:\nDaily backups to S3 with Restic and systemd timers\nWarning The only problem with backing up files this way is that with containers that are always running, you need to make sure that the files are flushed to disk before the backup starts, otherwise your backup could become corrupted. For files that are only written to once (photos, videos, etc.) this might not be such a big deal, but for files that are constantly changing (e.g., databases) this is a problem.\nTip Evaluating this Restic script:\nPros:\nIt’s a self contained script not dependent on Docker. It can backup several directories and upload to an offsite S3 bucket. Point the script at any directory and it will make a backup of it (e.g., /home/pi/, /var/lib/docker/volumes [see Cons].) It supports a space-efficient incremental backup strategy. It’s a good option for backup of home directories and large media folders. Cons:\nNo integration with Docker; it cannot shutdown containers before backup. Backup of /var/lib/docker/volumes is not 100% safe. Files that are modified during the backup may become corrupted. Restoration requires the original script and for you to re-install Restic. Backup-Volume Backup-Volume is another backup tool that is specifically configured to backup Docker volumes and uploading archives to offsite storage (S3, SSH, DropBox).\nBackup-Volume can only handle complete backups (no incremental storage). For small datasets this is ideal, because each backup gets stored in a separate backup-XXXX.tar.gz, and its easy to restore with one file. For larger datasets, the duplication of backup files would be prohibitively expensive/wasteful (although you can tune the retention and pruning parameters to save some space, it won’t compare to the efficiency of Restic).\nBackup-Volume has a trick it can use in its favor: it can automatically stop and start containers before and after the backup runs. This makes this style of backup much safer for write intensive volumes (e.g., databases) and ensures that the data gets flushed before the backup starts.\nTip Evaluating Backup-Volume:\nPros:\nSpecifically designed to backup Docker volumes on a cron-like schedule. Manages the lifecycle of the containers to shut them down before a backup starts and to restart them afterward. Each backup is contained in a single file (backup-XXXX.tar.gz) which is uploaded to your S3 provider. Restoration is easy, just download the latest tarball and extract it. Automatic pruning of old archives helps to save some space. Cons:\nNo incremental backup support. Each backup duplicates the entire dataset. Ill-suited for large datasets. Setup Backup-Volume Prepare an S3 bucket offsite You may want to use your own minio S3 service (preferably installed on a separate offsite server), or a third party provider (AWS S3, DigitalOcean Spaces, Wasabi, etc.)\nYou will need to provide the S3 bucket and credentials that the backup process will use when uploading archives:\nS3 Endpoint domain. e.g., s3.example.com. S3 bucket name. e.g., test S3 access key id. e.g., test. S3 secret key. e.g., xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx. Configure Backup-Volume Run this on your Raspberry Pi ## Configures the default backup-volume instance:\u0001 pi make backup-volume config Select multiple existing volumes to backup together as one archive:\n(stdout) ? Select all the volumes to backup \u003e [x] test1_data [ ] forgejo_data [x] icecast_config [ ] icecast_logs [ ] mosquitto_mosquitto [ ] traefik_geoip_database v [ ] traefik_traefik Choose the backup schedule in cron format :\n(stdout) BACKUP_CRON_EXPRESSION: Enter the cron expression (eg. @daily) : @every 24h Tip Other example schedules:\n@every 1h15m @daily @weekly See more in the .env-dist file Choose the retention length (number of days) to keep backup archives before automatic pruning happens:\n(stdout) BACKUP_RETENTION_DAYS: Rotate backups older than how many days? (eg. 30) : 30 You can choose any of the supported storage mechanisms. For demo purposes, choose S3:\n(stdout) \u003e Which remote storage do you want to use? s3 BACKUP_AWS_ENDPOINT: Enter the S3 endpoint (e.g., s3.example.com) : s3.d.example.com BACKUP_AWS_S3_BUCKET_NAME: Enter the S3 bucket name (e.g., my-bucket) : backup-test-1 BACKUP_AWS_ACCESS_KEY_ID: Enter the S3 access key id (e.g., my-access-key) : backup-test-1 BACKUP_AWS_SECRET_ACCESS_KEY: Enter the S3 secret access key : OEuL3lMSdvdoFyVjEQTM4Trj/7VhHq7Q7cOFEpQPuxMHxsTVK3Hxne7st6Ty BACKUP_AWS_S3_PATH: Choose a directory inside the bucket (blank for root) : Tip You should use a dedicated bucket for each backup instance, or you can share the same bucket between several instances, as long as you are careful to configure a unique BACKUP_AWS_S3_PATH bucket sub-directory for each instance.\nYou may optionally preserve an additional copy of the archive in a local volume:\n(stdout) \u003e Do you want to keep a local backup in addition to the remote one? No You can choose to turn on notifications (see separate instructions below.)\n(stdout) ? Do you want to receive notifications for backup failure? \u003e No. Yes, via email. Yes, via webhook. Install Run this on your Raspberry Pi ## installs the default backup instance: pi make backup-volume install Instances All volume selections will backup to the same archive on the same schedule. To back up different volumes on different schedules, you should create more than one instance of Backup-Volume to create separate configs:\nRun this on your Raspberry Pi ## Creates a new backup instance named test: pi make backup-volume instance instance=test pi make backup-volume install instance=test Verify backup schedule Run this on your Raspberry Pi pi make backup-volume logs (stdout) backup-1 | 2024-10-16T02:37:00.263838944Z time=2024-10-16T02:37:00.262Z level=INFO msg=\"Successfully scheduled backup from environment with expression @daily\" backup-1 | 2024-10-16T02:37:00.266773318Z time=2024-10-16T02:37:00.266Z level=INFO msg=\"The backup will start at 12:00 AM\" Tip You should see a plain text log message describing when the backup will occur (The backup will start at 12:00 AM), except it will be ommitted if you use the @every syntax.\nRestore To restore a volume from a backup, simply untar the archive into the appropriate directory under /var/lib/docker/volumes.\nNotifications In the event of a failed backup job, a notification can be sent to a configurable receiver with Shoutrrr (including Email, Matrix, Discord, Ntfy, IFTTT etc.)\nEmail notifications Info To enable email notifications, you must setup postfix-relay separately and configure it to allow clients from the the backup-volume network to send mail.\n(stdout) ? Do you want to receive notifications for backup failure? No. \u003e Yes, via email. Yes, via webhook. Enter the sender email address : backup-volume-default@pi5.forwarding.network Enter the recipient email address : test@example.com Matrix notifications via webhook You will need to setup the Matrix Hookshot bot in order to receive a generic webhook from Backup-Volume that notifies the Matrix room you share with the bot.\nCreate a new room and invite the hookshot bot to it. Message the room: !hookshot setup-widget. Open the room Extensions tab and click on the Hookshot extension. Create a new Inbound (Generic) Webhook. Name the webhook backup-volume.example.com after your backup-volume instance. Copy the long URL it gives you, e.g., https://matrix.example.com/hookshot/webhooks/webhook/xxxxxx. Click Save. Reconfigure the .env_{CONTEXT}_{INSTANCE} file of the backup-volume instance, setting the notification URL as a Generic webhook:\nRun this on your Raspberry Pi pi make backup-volume reconfigure var=BACKUP_NOTIFICATION_URLS=\"generic://matrix.example.com/hookshot/webhooks/webhook/xxxxx?template=json\" Tip Important: the Shoutrrr webhook notification URL should start with generic:// (not https://). It should end with ?template=json.\nRe-install to load the new config:\nRun this on your Raspberry Pi pi make backup-volume install To test the notification, you can consider setting BACKUP_CRON_EXPRESSION=@every 1m and change the S3 credentials so that they are incorrect, thus triggering a failure notification to be sent.\nYou should see the JSON notification in the channel, which unfortunately is not formatted very nicely :\nExample matrix message: { “message”: “Running backup-volume failed with error: main.(*script).copyArchive: error copying archive: s3.(*s3Storage).Copy: error uploading backup to remote storage: [Message]: ‘The specified bucket does not exist.’, [Code]: NoSuchBucket, [StatusCode]: 404\\n\\nLog output of the failed run was:\\n\\ntime=2024-10-16T19:45:27.092Z level=INFO msg=\\“Stopping 1 out of 26 running container(s) as they were labeled backup-volume.stop-during-backup=true.\\\"\\ntime=2024-10-16T19:45:27.713Z level=INFO msg=\\“Created backup of `/backup` at `/tmp/backup-default-2024-10-16T19-45-27.tar.gz`.\\\"\\ntime=2024-10-16T19:45:27.972Z level=INFO msg=\\“Restarted 1 container(s).\\\"\\ntime=2024-10-16T19:45:28.259Z level=INFO msg=\\“Removed tar file `/tmp/backup-default-2024-10-16T19-45-27.tar.gz`.\\\"\\n”, “title”: “Failure running backup-volume at 2024-10-16T19:45:27Z” }", "description": "Backup of native machines is much harder than for virtual machines, that’s just the way it goes. With VMs, your hypervisor should have a builtin backup feature which can suspend (pause) the entire machine, make a snapshot of the disk and the entire RAM contents, resume the machine, and continue backing up the snapshot in the background. If you have the luxury of running your server as a VM (e.g., Proxmox PVE, or any cloud provider), it makes backups so much easier.", "tags": [], "title": "Native Backup", diff --git a/license/index.html b/license/index.html index b3d1bdf60..9ee2e9333 100644 --- a/license/index.html +++ b/license/index.html @@ -33,17 +33,17 @@ LICENSE :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/linux-workstation/app-users/digitalocean/index.html b/linux-workstation/app-users/digitalocean/index.html index fd6c6319b..266bf6d5f 100644 --- a/linux-workstation/app-users/digitalocean/index.html +++ b/linux-workstation/app-users/digitalocean/index.html @@ -29,17 +29,17 @@ DigitalOcean CLI (doctl) :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/linux-workstation/app-users/index.html b/linux-workstation/app-users/index.html index 769919627..9626cc0cb 100644 --- a/linux-workstation/app-users/index.html +++ b/linux-workstation/app-users/index.html @@ -29,17 +29,17 @@ Application users :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/linux-workstation/config/emacs-on-fedora/index.html b/linux-workstation/config/emacs-on-fedora/index.html index b4f3db87b..275a77d59 100644 --- a/linux-workstation/config/emacs-on-fedora/index.html +++ b/linux-workstation/config/emacs-on-fedora/index.html @@ -25,17 +25,17 @@ Install Emacs Because Sway runs on Wayland, you’ll want to install the Wayland (pgtk) version of Emacs. In Fedora 40 onwards, the Wayland (pgtk) version is already the default. For Fedora 39, you can use this COPR (a COPR is to Fedora what PPA is to Ubuntu and what AUR is to Arch Linux), which includes a custom build for Wayland (pgtk)."> Emacs :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/linux-workstation/config/firefox/index.html b/linux-workstation/config/firefox/index.html index b7e694271..339119229 100644 --- a/linux-workstation/config/firefox/index.html +++ b/linux-workstation/config/firefox/index.html @@ -25,17 +25,17 @@ Remove clutter Remove Firefox View, right click the upper left icon and select Remove from toolbar. Remove existing bookmarks from bookmark bar, right click each one and select Delete. Remove Pocket, right click the pocket icon in the upper right toolbar, select Remove from toolbar Remove Firefox Account icon, select Remove from toolbar Firefox Settings Go into the Firefox settings: click the “hamburger” menu in the top right toolbar."> Firefox :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/linux-workstation/config/index.html b/linux-workstation/config/index.html index 3726aca05..9fc4e8404 100644 --- a/linux-workstation/config/index.html +++ b/linux-workstation/config/index.html @@ -21,17 +21,17 @@ Config :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/linux-workstation/config/ssh/index.html b/linux-workstation/config/ssh/index.html index bb9f3b7b9..b3928e49a 100644 --- a/linux-workstation/config/ssh/index.html +++ b/linux-workstation/config/ssh/index.html @@ -25,17 +25,17 @@ Access to a server’s console shell, remotely. Transfer files between the server and client (using rsync, scp, or sftp). Create network tunnels to access private servers, in both directions, either on the server, or on the client."> SSH :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/linux-workstation/config/sway/index.html b/linux-workstation/config/sway/index.html index 155c39a68..d605a2fa5 100644 --- a/linux-workstation/config/sway/index.html +++ b/linux-workstation/config/sway/index.html @@ -25,17 +25,17 @@ Sway Config The Fedora Atomic Sway edition includes a default configuration for Sway. It’s pretty nice out of the box, and so if you like it, you can just use it."> Sway :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/linux-workstation/config/toolbox/index.html b/linux-workstation/config/toolbox/index.html index 89e40fd8b..a676625e9 100644 --- a/linux-workstation/config/toolbox/index.html +++ b/linux-workstation/config/toolbox/index.html @@ -21,17 +21,17 @@ Toolbox :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/linux-workstation/firewall/index.html b/linux-workstation/firewall/index.html index 2b85b4db0..491707c80 100644 --- a/linux-workstation/firewall/index.html +++ b/linux-workstation/firewall/index.html @@ -29,17 +29,17 @@ Don’t mess with it Warning Fedora Atomic installs a good default zone for workstation use, named public."> Firewall :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/linux-workstation/index.html b/linux-workstation/index.html index 2dbc16212..f9d4a569c 100644 --- a/linux-workstation/index.html +++ b/linux-workstation/index.html @@ -25,17 +25,17 @@ Linux Workstation :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/linux-workstation/install/index.html b/linux-workstation/install/index.html index 746cca5e6..5486f0851 100644 --- a/linux-workstation/install/index.html +++ b/linux-workstation/install/index.html @@ -29,17 +29,17 @@ [bash]: Run this on your workstation: lsblk | grep disk (stdout) NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS sda 8:0 0 1."> Install Linux (Fedora Atomic) :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/linux-workstation/introduction/fedora-sway-atomic/index.html b/linux-workstation/introduction/fedora-sway-atomic/index.html index 6bec94e6a..88ba3cf2e 100644 --- a/linux-workstation/introduction/fedora-sway-atomic/index.html +++ b/linux-workstation/introduction/fedora-sway-atomic/index.html @@ -29,17 +29,17 @@ Sway is a minimal tiling window manager for Wayland. It is ideal for efficient keyboard centric development and for getting out of your way."> Fedora Sway Atomic :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/linux-workstation/introduction/index.html b/linux-workstation/introduction/index.html index b73e8cf0d..2e02de909 100644 --- a/linux-workstation/introduction/index.html +++ b/linux-workstation/introduction/index.html @@ -25,17 +25,17 @@ Introduction :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/linux-workstation/introduction/requirements/index.html b/linux-workstation/introduction/requirements/index.html index 4a5964548..b41cc0490 100644 --- a/linux-workstation/introduction/requirements/index.html +++ b/linux-workstation/introduction/requirements/index.html @@ -25,17 +25,17 @@ An x86_64 desktop or laptop computer to install to. A USB drive for copying the .iso installer to. A solokey or other FIDO2 compatible hardware authentication key. (This is optional, but highly recommended for storing secure shell keys, sudo 2FA, and logging into websites with Webauthn.) "> Requirements :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/linux-workstation/kvm-libvirt/cloud-init/config-vm/index.html b/linux-workstation/kvm-libvirt/cloud-init/config-vm/index.html index 50566c295..6b7601cab 100644 --- a/linux-workstation/kvm-libvirt/cloud-init/config-vm/index.html +++ b/linux-workstation/kvm-libvirt/cloud-init/config-vm/index.html @@ -33,17 +33,17 @@ Fedora 40 [bash]: Set temporary environment variables OS_VARIANT=fedora40 CLOUD_IMAGE=https://download."> Configure VM (cloud-init) :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/linux-workstation/kvm-libvirt/cloud-init/create-vm/index.html b/linux-workstation/kvm-libvirt/cloud-init/create-vm/index.html index 61e38ca22..9d588fb22 100644 --- a/linux-workstation/kvm-libvirt/cloud-init/create-vm/index.html +++ b/linux-workstation/kvm-libvirt/cloud-init/create-vm/index.html @@ -21,17 +21,17 @@ Create VM (cloud-init) :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/linux-workstation/kvm-libvirt/cloud-init/index.html b/linux-workstation/kvm-libvirt/cloud-init/index.html index f57c493f0..4be4fed60 100644 --- a/linux-workstation/kvm-libvirt/cloud-init/index.html +++ b/linux-workstation/kvm-libvirt/cloud-init/index.html @@ -21,17 +21,17 @@ Cloud-Init VMs :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/linux-workstation/kvm-libvirt/dedicated-vm-user/index.html b/linux-workstation/kvm-libvirt/dedicated-vm-user/index.html index 379eaf9cf..34367f5a4 100644 --- a/linux-workstation/kvm-libvirt/dedicated-vm-user/index.html +++ b/linux-workstation/kvm-libvirt/dedicated-vm-user/index.html @@ -25,17 +25,17 @@ This separation from the normal account you use is important to limit the privileges that you have over the VM infrastructure. Your normal account should be able to SSH into the VM and have full root privleges inside the VM."> Create VM admin :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/linux-workstation/kvm-libvirt/index.html b/linux-workstation/kvm-libvirt/index.html index 138324a77..e868ee365 100644 --- a/linux-workstation/kvm-libvirt/index.html +++ b/linux-workstation/kvm-libvirt/index.html @@ -25,17 +25,17 @@ KVM / libvirt :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/linux-workstation/kvm-libvirt/install-libvirtd/index.html b/linux-workstation/kvm-libvirt/install-libvirtd/index.html index a82aeadb8..414eca234 100644 --- a/linux-workstation/kvm-libvirt/install-libvirtd/index.html +++ b/linux-workstation/kvm-libvirt/install-libvirtd/index.html @@ -29,17 +29,17 @@ Packages for Fedora CoreOS [bash]: Run this on your workstation: sudo rpm-ostree install qemu-kvm libvirt virt-manager virt-viewer \ virt-install libvirt-daemon-config-network libvirt-daemon-kvm \ libguestfs-tools python3-libguestfs virt-top distrobox make Packages for traditional Fedora Workstation hosts Info These are the packages you would need to install on traditional Fedora Workstation (or Server, but not CoreOS nor Atomic hosts)"> Install libvirtd :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/linux-workstation/kvm-libvirt/public-routes/index.html b/linux-workstation/kvm-libvirt/public-routes/index.html index 02456ecfd..68c80c52e 100644 --- a/linux-workstation/kvm-libvirt/public-routes/index.html +++ b/linux-workstation/kvm-libvirt/public-routes/index.html @@ -29,17 +29,17 @@ Download the port-forwarding hook [bash]: Run this on your workstation: sudo mkdir -p /usr/local/src/ sudo su -c ""> Public routes to VMs :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/linux-workstation/kvm-libvirt/raw-disk/config/index.html b/linux-workstation/kvm-libvirt/raw-disk/config/index.html index ddd7e0ea0..2a1f9a1d1 100644 --- a/linux-workstation/kvm-libvirt/raw-disk/config/index.html +++ b/linux-workstation/kvm-libvirt/raw-disk/config/index.html @@ -21,17 +21,17 @@ Configure VM (raw disk) :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/linux-workstation/kvm-libvirt/raw-disk/create-vm/index.html b/linux-workstation/kvm-libvirt/raw-disk/create-vm/index.html index d2e1c134e..447d09d6f 100644 --- a/linux-workstation/kvm-libvirt/raw-disk/create-vm/index.html +++ b/linux-workstation/kvm-libvirt/raw-disk/create-vm/index.html @@ -33,17 +33,17 @@ Run this as the libvirt-admin user NAME=fedora-iot source ~/libvirt/${NAME}.env Create directories to hold the VM disks and config files: Run this as the libvirt-admin user mkdir -p ~/libvirt/{cloud-images,raw,disks,cloud-init,iso} Download the raw disk: Tip You only need to download each RAW_DISK once, they will be cached in ~/libvirt/raw, so they can be be reused."> Create VM (raw disk) :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/linux-workstation/kvm-libvirt/raw-disk/index.html b/linux-workstation/kvm-libvirt/raw-disk/index.html index 25231fa3c..530e54881 100644 --- a/linux-workstation/kvm-libvirt/raw-disk/index.html +++ b/linux-workstation/kvm-libvirt/raw-disk/index.html @@ -25,17 +25,17 @@ Raw disk VMs :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/linux-workstation/kvm-libvirt/setup-libvirtd/index.html b/linux-workstation/kvm-libvirt/setup-libvirtd/index.html index 915b2f19d..34bed5e0f 100644 --- a/linux-workstation/kvm-libvirt/setup-libvirtd/index.html +++ b/linux-workstation/kvm-libvirt/setup-libvirtd/index.html @@ -21,17 +21,17 @@ Setup libvirtd :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - + + + diff --git a/linux-workstation/kvm-libvirt/setup-workstation/index.html b/linux-workstation/kvm-libvirt/setup-workstation/index.html index 0ccb01944..b29c4058f 100644 --- a/linux-workstation/kvm-libvirt/setup-workstation/index.html +++ b/linux-workstation/kvm-libvirt/setup-workstation/index.html @@ -37,17 +37,17 @@ [bash]: Run this on your workstation: ssh debian-dev whoami (stdout) root Install Docker You’re now ready to use your VM as an install target for whatever you want."> Setup workstation SSH config :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/linux-workstation/kvm-libvirt/systemd/index.html b/linux-workstation/kvm-libvirt/systemd/index.html index fbac56386..d3abdd22d 100644 --- a/linux-workstation/kvm-libvirt/systemd/index.html +++ b/linux-workstation/kvm-libvirt/systemd/index.html @@ -29,17 +29,17 @@ Download libvirt python interface Tip You should now be in your normal workstation account Bash shell."> Systemd services to control VMs :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/linux-workstation/kvm-libvirt/vm-from-iso/bootstrap-coreos/index.html b/linux-workstation/kvm-libvirt/vm-from-iso/bootstrap-coreos/index.html index 803abfb55..542957ae7 100644 --- a/linux-workstation/kvm-libvirt/vm-from-iso/bootstrap-coreos/index.html +++ b/linux-workstation/kvm-libvirt/vm-from-iso/bootstrap-coreos/index.html @@ -29,17 +29,17 @@ SSH into Live environment From your normal workstation account, connect to the SSH server of the Fedora Live environment:"> Bootstrap CoreOS :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/linux-workstation/kvm-libvirt/vm-from-iso/configure-vm/index.html b/linux-workstation/kvm-libvirt/vm-from-iso/configure-vm/index.html index 1d3aad580..9e6cc9907 100644 --- a/linux-workstation/kvm-libvirt/vm-from-iso/configure-vm/index.html +++ b/linux-workstation/kvm-libvirt/vm-from-iso/configure-vm/index.html @@ -21,17 +21,17 @@ Configure VM with .iso boot :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/linux-workstation/kvm-libvirt/vm-from-iso/index.html b/linux-workstation/kvm-libvirt/vm-from-iso/index.html index abf860aac..a3d96c426 100644 --- a/linux-workstation/kvm-libvirt/vm-from-iso/index.html +++ b/linux-workstation/kvm-libvirt/vm-from-iso/index.html @@ -25,17 +25,17 @@ Create VM from .iso image :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/linux-workstation/kvm-libvirt/vm-from-iso/install-vm/index.html b/linux-workstation/kvm-libvirt/vm-from-iso/install-vm/index.html index b637c0fe6..881a914f3 100644 --- a/linux-workstation/kvm-libvirt/vm-from-iso/install-vm/index.html +++ b/linux-workstation/kvm-libvirt/vm-from-iso/install-vm/index.html @@ -29,17 +29,17 @@ [bash]: Run this on your workstation: xhost +local:libvirt-admin sudo -u libvirt-admin /bin/bash Tip The xhost line is to allow graphical apps (virt-viewer) from the other user appear on your display. You may need to play with xhost a few times to get it to work."> Boot VM from .iso :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/linux-workstation/layering-packages/index.html b/linux-workstation/layering-packages/index.html index a5b288a5c..79a9a75de 100644 --- a/linux-workstation/layering-packages/index.html +++ b/linux-workstation/layering-packages/index.html @@ -29,17 +29,17 @@ Layer packages with rpm-ostree To create efficient layers, and to lessen the burden of several reboots, you should try to install everything in one go, using as few layers as possible."> Layering packages :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/linux-workstation/sudo-2fa/get-your-solokey/index.html b/linux-workstation/sudo-2fa/get-your-solokey/index.html index fce4ece81..21f02146f 100644 --- a/linux-workstation/sudo-2fa/get-your-solokey/index.html +++ b/linux-workstation/sudo-2fa/get-your-solokey/index.html @@ -29,17 +29,17 @@ Recommended: Solo 2 USB-A (touch capacitive, but its long and sticks out of the USB port). Recommended: Solo 1 Tap USB-A (durable clicky button, but its long and sticks out of the USB port). Recommended: Somu (semi-permanent flush mount USB-A port, soft touch design). Get the “secure” version, don’t buy the “hacker” version. Buy at least two (and store one as a backup)."> Get your Solokey :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/linux-workstation/sudo-2fa/index.html b/linux-workstation/sudo-2fa/index.html index dbe5098e2..54c748bbc 100644 --- a/linux-workstation/sudo-2fa/index.html +++ b/linux-workstation/sudo-2fa/index.html @@ -29,17 +29,17 @@ Solokey authentication :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/linux-workstation/sudo-2fa/solo-v1/index.html b/linux-workstation/sudo-2fa/solo-v1/index.html index 1760e8933..023a16369 100644 --- a/linux-workstation/sudo-2fa/solo-v1/index.html +++ b/linux-workstation/sudo-2fa/solo-v1/index.html @@ -25,17 +25,17 @@ https://github.com/solokeys/solo1-cli/issues/151 https://github.com/solokeys/solo1-cli/discussions/156 Both of these are related to Fido2 v1.0.0. If you lock the version to the last known good version of 0.9.1, it will work:"> Solokey v1 :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/linux-workstation/sudo-2fa/solo-v2/index.html b/linux-workstation/sudo-2fa/solo-v2/index.html index 87487ca8c..adc993e88 100644 --- a/linux-workstation/sudo-2fa/solo-v2/index.html +++ b/linux-workstation/sudo-2fa/solo-v2/index.html @@ -37,17 +37,17 @@ Solokey v2 :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/linux-workstation/sudo-2fa/ssh-2fa/index.html b/linux-workstation/sudo-2fa/ssh-2fa/index.html index 7335cdc5e..d544f8151 100644 --- a/linux-workstation/sudo-2fa/ssh-2fa/index.html +++ b/linux-workstation/sudo-2fa/ssh-2fa/index.html @@ -21,17 +21,17 @@ SSH with Solokey :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/linux-workstation/sudo-2fa/sudo-2fa/index.html b/linux-workstation/sudo-2fa/sudo-2fa/index.html index 8e01af562..399bc7f1f 100644 --- a/linux-workstation/sudo-2fa/sudo-2fa/index.html +++ b/linux-workstation/sudo-2fa/sudo-2fa/index.html @@ -21,17 +21,17 @@ Sudo with Solokey :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/linux-workstation/upgrading/index.html b/linux-workstation/upgrading/index.html index d60ce6cab..032270056 100644 --- a/linux-workstation/upgrading/index.html +++ b/linux-workstation/upgrading/index.html @@ -33,17 +33,17 @@ [bash]: Run this on your workstation: sudo systemctl reboot The boot manager lists the last several images, which are still available to choose from."> Upgrading :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/portable-docker/acknowledgements/index.html b/portable-docker/acknowledgements/index.html index 7f03de9ea..19b6d130e 100644 --- a/portable-docker/acknowledgements/index.html +++ b/portable-docker/acknowledgements/index.html @@ -29,17 +29,17 @@ Thank you to DALL-E for drawing the illustrations. We forgive any misspellings and hallucinations."> Acknowledgements :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/portable-docker/configure-wireguard-tunnel/configure-raspberry-pi-wireguard-client/index.html b/portable-docker/configure-wireguard-tunnel/configure-raspberry-pi-wireguard-client/index.html index 919ebaab9..844ff102d 100644 --- a/portable-docker/configure-wireguard-tunnel/configure-raspberry-pi-wireguard-client/index.html +++ b/portable-docker/configure-wireguard-tunnel/configure-raspberry-pi-wireguard-client/index.html @@ -21,17 +21,17 @@ Configure Raspberry Pi WireGuard client :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/portable-docker/configure-wireguard-tunnel/configure-sentry-wireguard-server/index.html b/portable-docker/configure-wireguard-tunnel/configure-sentry-wireguard-server/index.html index 1f1404c6f..2e41fe04f 100644 --- a/portable-docker/configure-wireguard-tunnel/configure-sentry-wireguard-server/index.html +++ b/portable-docker/configure-wireguard-tunnel/configure-sentry-wireguard-server/index.html @@ -21,17 +21,17 @@ Configure sentry wireguard server :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/portable-docker/configure-wireguard-tunnel/index.html b/portable-docker/configure-wireguard-tunnel/index.html index c907cf761..0bde06a95 100644 --- a/portable-docker/configure-wireguard-tunnel/index.html +++ b/portable-docker/configure-wireguard-tunnel/index.html @@ -29,17 +29,17 @@ Configure WireGuard VPN :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/portable-docker/index.html b/portable-docker/index.html index 7fd300f7c..98e581951 100644 --- a/portable-docker/index.html +++ b/portable-docker/index.html @@ -26,20 +26,20 @@ - + Portable Docker: Build and Deploy Anywhere with WireGuard Tunneling :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/portable-docker/index.xml b/portable-docker/index.xml index c0b68672c..c0aaf7f68 100644 --- a/portable-docker/index.xml +++ b/portable-docker/index.xml @@ -61,7 +61,7 @@ https://book.rymcg.tech/portable-docker/install-core-services/index.html Mon, 01 Jan 0001 00:00:00 +0000 https://book.rymcg.tech/portable-docker/install-core-services/index.html - There are a few services you should consider installing before any others, which we will call core services: Index Forgejo Traefik-Forward-Auth (sentry authorization) + There are a few services you should consider installing before any others, which we will call core services: Index Forgejo Traefik-Forward-Auth (sentry authorization) Postfix-Relay (MTA) Install apps diff --git a/portable-docker/install-core-services/forgejo/index.html b/portable-docker/install-core-services/forgejo/index.html index c6a395e70..eb9b873e8 100644 --- a/portable-docker/install-core-services/forgejo/index.html +++ b/portable-docker/install-core-services/forgejo/index.html @@ -29,17 +29,17 @@ Self-hosting your own git repositories. Providing an OAuth2 identity service for your organization, facilitating single-sign on to all of your apps via Traefik’s forward-auth middleware. Forgejo is fundamental infrastructure You don’t need to install Forgejo on every server you make, but having at least one instance in your domain is recommended."> Forgejo :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/portable-docker/install-core-services/index.html b/portable-docker/install-core-services/index.html index 896ca3469..bf966e0aa 100644 --- a/portable-docker/install-core-services/index.html +++ b/portable-docker/install-core-services/index.html @@ -6,36 +6,36 @@ +Index Forgejo Traefik-Forward-Auth (sentry authorization) Postfix-Relay (MTA) "> +Index Forgejo Traefik-Forward-Auth (sentry authorization) Postfix-Relay (MTA) "> +Index Forgejo Traefik-Forward-Auth (sentry authorization) Postfix-Relay (MTA) "> - +Index Forgejo Traefik-Forward-Auth (sentry authorization) Postfix-Relay (MTA) "> + Install core services :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/portable-docker/install-core-services/index.xml b/portable-docker/install-core-services/index.xml index b7d2d4aa5..c48f2fdf6 100644 --- a/portable-docker/install-core-services/index.xml +++ b/portable-docker/install-core-services/index.xml @@ -3,7 +3,7 @@ Install core services :: book.rymcg.tech https://book.rymcg.tech/portable-docker/install-core-services/index.html - There are a few services you should consider installing before any others, which we will call core services: Index Forgejo Traefik-Forward-Auth (sentry authorization) + There are a few services you should consider installing before any others, which we will call core services: Index Forgejo Traefik-Forward-Auth (sentry authorization) Postfix-Relay (MTA) Hugo en-us @@ -21,5 +21,12 @@ https://book.rymcg.tech/portable-docker/install-core-services/traefik-forward-auth/index.html Sentry authorization Some apps may already have their own authentication mechanisms, while others may not. Sentry authorization creates a common authentication and authorization framework in front of your applications via Traefik middleware. Sentry authorization happens before any existing auth mechanisms in the app itself, and so it acts as a front door gatekeeper for your apps. It can’t control what users are allowed to do once they get in, but it does control who is allowed in through the front door. + + Postfix-Relay (MTA) + https://book.rymcg.tech/portable-docker/install-core-services/postfix-relay/index.html + Mon, 01 Jan 0001 00:00:00 +0000 + https://book.rymcg.tech/portable-docker/install-core-services/postfix-relay/index.html + Many apps require to send email for various purposes. Rather than configure each such container with your secret mail credentials, you can configure a single central mail forwarding service with postfix-relay. --- title: Authorized container networks may bridge with the Postfix-Relay to send outgoing email. --- graph TD; subgraph Docker network A[Container A] -->|private mail-only network| D[Postfix-Relay] B[Container B] -->|private mail-only network| D[Postfix-Relay] C[Container C] -.- F[Blocked] end D -->|Internet| E[Public SMTP server] E --> G[Allowed Email recipient] E --> H[Allowed Email recipient] E -. + \ No newline at end of file diff --git a/portable-docker/install-core-services/postfix-relay/index.html b/portable-docker/install-core-services/postfix-relay/index.html new file mode 100644 index 000000000..dbbaed212 --- /dev/null +++ b/portable-docker/install-core-services/postfix-relay/index.html @@ -0,0 +1,469 @@ + + + + + + + + + + + + + + + + + + + + + + + Postfix-Relay (MTA) :: book.rymcg.tech + + + + + + + + + + + + + + + +
+
+ +
+
+
+
+
+
+ +

Postfix-Relay (MTA)

+ +

Many apps require to send email for various purposes. Rather than +configure each such container with your secret mail credentials, you +can configure a single central mail forwarding service with +postfix-relay.

+ +
+---
+title: Authorized container networks may bridge with the Postfix-Relay to send outgoing email.
+---
+graph TD;
+subgraph Docker network
+    A[Container A] -->|private mail-only network| D[Postfix-Relay]
+    B[Container B] -->|private mail-only network| D[Postfix-Relay]
+    C[Container C] -.- F[Blocked]
+end
+D -->|Internet| E[Public  SMTP server]
+E --> G[Allowed Email recipient]
+E --> H[Allowed Email recipient]
+E -.- I[Blocked Email recipient]
+
+

Register the upstream SMTP service

+

You will need access to a public email (SMTP) service for outgoing +mail. Gather the following information from your provider:

+
    +
  • The SMTP server domain, e.g., mail.example.com.
  • +
  • The port, e.g., 465 (TLS) or 587 (STARTTLS).
  • +
  • The username, e.g., me@example.com.
  • +
  • The password, e.g., hunter2.
  • +
+

Configure Postfix-Relay

+ + +
+
+ Run this on your Raspberry Pi
+
+
+pi make postfix-relay config
+
+
+
+ + +

Enter the domain name for this postfix instance:

+
+
(stdout)
+
+
+POSTFIX_RELAY_TRAEFIK_HOST: Enter the domain name for this instance
+
+: smtp.d.example.com
+
+
+
+ +

Enter the upstream SMTP server connection details:

+
+
(stdout)
+
+
+POSTFIX_RELAY_RELAYHOST: Enter the outgoing SMTP server domain:port (eg. smtp.example.com:587)
+
+: mail.example.com:465
+
+POSTFIX_RELAY_RELAYHOST_USERNAME: Enter the outgoing SMTP server username
+
+: username@example.com
+
+POSTFIX_RELAY_RELAYHOST_PASSWORD: Enter the outgoing SMTP server password
+
+: xxxxxxxxxxxxxxxxxxxx
+
+
+
+ +

Select which network subdomains should be masked at the root domain +(this is optional, and can be used to hide private subdomains from the +email headers):

+
+
(stdout)
+
+
+POSTFIX_RELAY_MASQUERADED_DOMAINS: Enter the root domains (separated by space) that should mask its sub-domains
+
+: example.com example.org
+
+
+
+ +

Install

+ + +
+
+ Run this on your Raspberry Pi
+
+
+pi make postfix-relay install
+
+
+
+ + +

Test sending mail

+ + +
+
+ Run this on your Raspberry Pi
+
+
+(
+RECIPIENT="recipient@example.com"
+SENDER="root@localhost"
+SUBJECT="Test Email"
+BODY="This is a test email sent from Docker."
+
+docker run --rm \
+  --network postfix-relay_default \
+  -e RECIPIENT="$RECIPIENT" \
+  -e SENDER="$SENDER" \
+  -e SUBJECT="$SUBJECT" \
+  -e BODY="$BODY" \
+  alpine sh -c 'apk add --no-cache msmtp && \
+  echo -e "Subject: $SUBJECT\n\n$BODY" | \
+  msmtp --from="$SENDER" \
+        --host=postfix-relay-postfix-relay-1 \
+        --port=587 \
+        --tls=off \
+        --tls-starttls=off \
+        "$RECIPIENT" && \
+        echo "Email sent" || \
+        echo "Email failed to send"'
+)
+
+
+
+ + +

Next steps

+
    +
  • Install apps.
  • +
+ + +
+
+
+
+ + + + + + + + + + + + + + + + + + diff --git a/portable-docker/install-core-services/traefik-forward-auth/index.html b/portable-docker/install-core-services/traefik-forward-auth/index.html index 122b79d4f..ac02cba14 100644 --- a/portable-docker/install-core-services/traefik-forward-auth/index.html +++ b/portable-docker/install-core-services/traefik-forward-auth/index.html @@ -19,19 +19,19 @@ - + Traefik-Forward-Auth (sentry authorization) :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/portable-docker/install-web-services/homepage/index.html b/portable-docker/install-web-services/homepage/index.html index bf8367d48..73ce76498 100644 --- a/portable-docker/install-web-services/homepage/index.html +++ b/portable-docker/install-web-services/homepage/index.html @@ -29,17 +29,17 @@ (stdout) HOMEPAGE_TRAEFIK_HOST: Enter the homepage domain name (eg. homepage.example.com) : homepage.pi.example.com HOMEPAGE_WEBHOOK_HOST: Enter the separate webhook domain name (eg. homepage-webhook.example.com) : homepage-webhook.pi.example.com It is recommended to enable some form of sentry authorization to protect homepage, e."> Homepage :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/portable-docker/install-web-services/immich/index.html b/portable-docker/install-web-services/immich/index.html index a496f369f..cccac619c 100644 --- a/portable-docker/install-web-services/immich/index.html +++ b/portable-docker/install-web-services/immich/index.html @@ -21,17 +21,17 @@ Immich :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/portable-docker/install-web-services/index.html b/portable-docker/install-web-services/index.html index fb1270b5b..857787176 100644 --- a/portable-docker/install-web-services/index.html +++ b/portable-docker/install-web-services/index.html @@ -25,17 +25,17 @@ Install apps :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/portable-docker/install-web-services/jupyterlab/index.html b/portable-docker/install-web-services/jupyterlab/index.html index e72350a7c..39ff71cb1 100644 --- a/portable-docker/install-web-services/jupyterlab/index.html +++ b/portable-docker/install-web-services/jupyterlab/index.html @@ -25,17 +25,17 @@ Configure Jupyterlab Run this on your Raspberry Pi pi make jupyterlab config Install Jupyterlab Run this on the Raspberry Pi pi make jupyterlab install wait Add a new route on the sentry (droplet) Run this on the Raspberry Pi sentry make traefik config (stdout) ?"> Jupyterlab :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/portable-docker/install-web-services/minio-s3/index.html b/portable-docker/install-web-services/minio-s3/index.html index 8069f8e0d..56e86265b 100644 --- a/portable-docker/install-web-services/minio-s3/index.html +++ b/portable-docker/install-web-services/minio-s3/index.html @@ -25,17 +25,17 @@ Tip Running MinIO on a single Raspberry Pi is perfect for personal use. However, for heavier production use, you will need to plan to use beefier hardware with redundant storage."> MinIO S3 (and Filestash) :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/portable-docker/install-web-services/nginx-and-php/index.html b/portable-docker/install-web-services/nginx-and-php/index.html index ac278e183..cff05c7da 100644 --- a/portable-docker/install-web-services/nginx-and-php/index.html +++ b/portable-docker/install-web-services/nginx-and-php/index.html @@ -25,17 +25,17 @@ Configure Nginx Run this on your Raspberry Pi pi make nginx config Make sure you choose a unique domain for this service (www is also the default for thttpd, so if you installed that too, just make sure this is unique:)"> Nginx and PHP :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/portable-docker/install-web-services/sftp/index.html b/portable-docker/install-web-services/sftp/index.html index 0cb9ee117..1a933bd30 100644 --- a/portable-docker/install-web-services/sftp/index.html +++ b/portable-docker/install-web-services/sftp/index.html @@ -25,17 +25,17 @@ Install a demo web server (thttpd) Thttpd is a tiny static HTTP server for hosting websites. It will be used for demonstration purposes in showing the effect of transferring files directly into its volume, via SFTP."> SFTP (and Thttpd) :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/portable-docker/install-web-services/yourls/index.html b/portable-docker/install-web-services/yourls/index.html index 7a8fb0602..c692dfad4 100644 --- a/portable-docker/install-web-services/yourls/index.html +++ b/portable-docker/install-web-services/yourls/index.html @@ -21,17 +21,17 @@ Yourls :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/portable-docker/introduction/index.html b/portable-docker/introduction/index.html index 92f220afa..9b95e1c8d 100644 --- a/portable-docker/introduction/index.html +++ b/portable-docker/introduction/index.html @@ -25,17 +25,17 @@ I use this as a tiny web server that I can take anywhere I go."> Introduction :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/portable-docker/maintainence/backup/index.html b/portable-docker/maintainence/backup/index.html index eb3507f38..6100ccdc0 100644 --- a/portable-docker/maintainence/backup/index.html +++ b/portable-docker/maintainence/backup/index.html @@ -19,19 +19,19 @@ - + Native Backup :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/portable-docker/maintainence/index.html b/portable-docker/maintainence/index.html index 55f6481ae..721188d8c 100644 --- a/portable-docker/maintainence/index.html +++ b/portable-docker/maintainence/index.html @@ -21,17 +21,17 @@ Maintainence :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/portable-docker/maintainence/troubleshooting/index.html b/portable-docker/maintainence/troubleshooting/index.html index f54849c10..1bdbb6f3e 100644 --- a/portable-docker/maintainence/troubleshooting/index.html +++ b/portable-docker/maintainence/troubleshooting/index.html @@ -25,17 +25,17 @@ [bash]: Run this on your workstation: ## Just leave this running in a separate terminal as you keep working.. sudo dmesg -w Disable power saving on NVME storage How to disable power saving on the NVME drive Out of two identical kits, I encountered one error in the kernel log on one machine but not on the other, so you may or may not run into this error:"> Troubleshooting :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/portable-docker/maintainence/upgrade/index.html b/portable-docker/maintainence/upgrade/index.html index da4e37cc6..961d5c8b8 100644 --- a/portable-docker/maintainence/upgrade/index.html +++ b/portable-docker/maintainence/upgrade/index.html @@ -25,17 +25,17 @@ The version of the app is usually controlled via an environment variable named PROJECT_IMAGE or PROJECT_VERSION. For some apps, this will be labeled as latest so that it always installs the latest version, while others are locked to a specific know working version."> Upgrade :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/portable-docker/set-up-cloud-sentry/configure-d-rymcg-tech-for-sentry/index.html b/portable-docker/set-up-cloud-sentry/configure-d-rymcg-tech-for-sentry/index.html index 8f1fedb9c..58509bd90 100644 --- a/portable-docker/set-up-cloud-sentry/configure-d-rymcg-tech-for-sentry/index.html +++ b/portable-docker/set-up-cloud-sentry/configure-d-rymcg-tech-for-sentry/index.html @@ -21,17 +21,17 @@ Configure d.rymcg.tech for the sentry :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/portable-docker/set-up-cloud-sentry/index.html b/portable-docker/set-up-cloud-sentry/index.html index 3748163ff..86b4710a5 100644 --- a/portable-docker/set-up-cloud-sentry/index.html +++ b/portable-docker/set-up-cloud-sentry/index.html @@ -21,17 +21,17 @@ Set up sentry Droplet :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/portable-docker/set-up-cloud-sentry/launch-digitalocean-droplet/index.html b/portable-docker/set-up-cloud-sentry/launch-digitalocean-droplet/index.html index 8d251ef16..32246b11c 100644 --- a/portable-docker/set-up-cloud-sentry/launch-digitalocean-droplet/index.html +++ b/portable-docker/set-up-cloud-sentry/launch-digitalocean-droplet/index.html @@ -21,17 +21,17 @@ Launch DigitalOcean droplet :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/portable-docker/set-up-cloud-sentry/set-up-docker-context/index.html b/portable-docker/set-up-cloud-sentry/set-up-docker-context/index.html index 411719514..610c99e32 100644 --- a/portable-docker/set-up-cloud-sentry/set-up-docker-context/index.html +++ b/portable-docker/set-up-cloud-sentry/set-up-docker-context/index.html @@ -25,17 +25,17 @@ Append to the SSH config on the Pi Run this on the Raspberry Pi cat <<EOF >> ~/.ssh/config Host sentry User root Hostname sentry.example.com ControlMaster auto ControlPersist yes ControlPath /tmp/ssh-%u-%r@%h:%p EOF Tip The Hostname value should point to the same name you created the DNS entry for the sentry."> Configure the sentry context on the Pi :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/portable-docker/set-up-dns/create-digitalocean-api-token-for-acme-challenge/index.html b/portable-docker/set-up-dns/create-digitalocean-api-token-for-acme-challenge/index.html index ceff7e584..01dca2c29 100644 --- a/portable-docker/set-up-dns/create-digitalocean-api-token-for-acme-challenge/index.html +++ b/portable-docker/set-up-dns/create-digitalocean-api-token-for-acme-challenge/index.html @@ -29,17 +29,17 @@ DNS is also a part of the TLS certificate request process with Let’s Encrypt (via ACME DNS-01 challenge)."> Generate DigitalOcean API token for ACME challenge :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/portable-docker/set-up-dns/create-digitalocean-api-token/index.html b/portable-docker/set-up-dns/create-digitalocean-api-token/index.html index 617393f64..f1bd745aa 100644 --- a/portable-docker/set-up-dns/create-digitalocean-api-token/index.html +++ b/portable-docker/set-up-dns/create-digitalocean-api-token/index.html @@ -29,17 +29,17 @@ Sign up for a DigitalOcean account (using this referral link helps support this site), and follow along to set up your domain’s DNS."> Add the domain to DigitalOcean DNS :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/portable-docker/set-up-dns/index.html b/portable-docker/set-up-dns/index.html index 82de0bd6e..d0d20b2db 100644 --- a/portable-docker/set-up-dns/index.html +++ b/portable-docker/set-up-dns/index.html @@ -25,17 +25,17 @@ Set up DNS :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/portable-docker/set-up-dns/register-domain/index.html b/portable-docker/set-up-dns/register-domain/index.html index 1a57d9862..8b7fca84c 100644 --- a/portable-docker/set-up-dns/register-domain/index.html +++ b/portable-docker/set-up-dns/register-domain/index.html @@ -25,17 +25,17 @@ Domain name registration The public domain name registration system is controlled as a scarce resource that you must pay for the use of."> Register a domain name :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/portable-docker/set-up-public-ssh-reverse-tunnel/index.html b/portable-docker/set-up-public-ssh-reverse-tunnel/index.html index c25293722..fe28b92f3 100644 --- a/portable-docker/set-up-public-ssh-reverse-tunnel/index.html +++ b/portable-docker/set-up-public-ssh-reverse-tunnel/index.html @@ -25,17 +25,17 @@ Set up public SSH :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/portable-docker/set-up-raspberry-pi/build-your-pi/index.html b/portable-docker/set-up-raspberry-pi/build-your-pi/index.html index c26fafee3..74afd450d 100644 --- a/portable-docker/set-up-raspberry-pi/build-your-pi/index.html +++ b/portable-docker/set-up-raspberry-pi/build-your-pi/index.html @@ -29,17 +29,17 @@ Geeekpi / 52Pi case, heatsink, NVME shield, and power supply This kit comes with the NVME shield, which is an adapter (hat) to install on top of the Raspberry Pi 5 motherboard."> Build your Raspberry Pi :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/portable-docker/set-up-raspberry-pi/index.html b/portable-docker/set-up-raspberry-pi/index.html index 5b010e67d..4f414685b 100644 --- a/portable-docker/set-up-raspberry-pi/index.html +++ b/portable-docker/set-up-raspberry-pi/index.html @@ -21,17 +21,17 @@ Set up Raspberry Pi :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/portable-docker/set-up-raspberry-pi/install-d-rymcg-tech/index.html b/portable-docker/set-up-raspberry-pi/install-d-rymcg-tech/index.html index f1c3a5ca9..145dc54f0 100644 --- a/portable-docker/set-up-raspberry-pi/install-d-rymcg-tech/index.html +++ b/portable-docker/set-up-raspberry-pi/install-d-rymcg-tech/index.html @@ -25,17 +25,17 @@ Run this on the Raspberry Pi cat <<'EOF' >> ~/.bashrc export EDITOR=nano ## d."> Install d.rymcg.tech :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/portable-docker/set-up-raspberry-pi/install-docker/index.html b/portable-docker/set-up-raspberry-pi/install-docker/index.html index 523132d5c..2253a99d5 100644 --- a/portable-docker/set-up-raspberry-pi/install-docker/index.html +++ b/portable-docker/set-up-raspberry-pi/install-docker/index.html @@ -21,17 +21,17 @@ Install Docker :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/portable-docker/set-up-raspberry-pi/install-raspbian/index.html b/portable-docker/set-up-raspberry-pi/install-raspbian/index.html index 9c1e23fd6..9730e863b 100644 --- a/portable-docker/set-up-raspberry-pi/install-raspbian/index.html +++ b/portable-docker/set-up-raspberry-pi/install-raspbian/index.html @@ -37,17 +37,17 @@ Choose your model of Raspberry Pi."> Install Raspberry Pi OS :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/portable-docker/set-up-raspberry-pi/install-traefik/index.html b/portable-docker/set-up-raspberry-pi/install-traefik/index.html index c142dc686..36b1aa3e5 100644 --- a/portable-docker/set-up-raspberry-pi/install-traefik/index.html +++ b/portable-docker/set-up-raspberry-pi/install-traefik/index.html @@ -25,17 +25,17 @@ Basic Traefik config Run this on the Raspberry Pi pi make traefik config This presents the interactive configuration menu for Traefik:"> Install Traefik :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/portable-docker/set-up-raspberry-pi/install-whoami/index.html b/portable-docker/set-up-raspberry-pi/install-whoami/index.html index 04b5b265e..b9425168d 100644 --- a/portable-docker/set-up-raspberry-pi/install-whoami/index.html +++ b/portable-docker/set-up-raspberry-pi/install-whoami/index.html @@ -25,17 +25,17 @@ Run this later after you install it: curl https://whoami.pi.example.com (stdout) Name: default Hostname: 38704012c4b3 IP: 127.0.0.1 IP: ::1 IP: 172.19.0.2 RemoteAddr: 172.19.0.1:34610 GET / HTTP/1.1 Host: whoami.example.com User-Agent: curl/7.88.1 Accept: */* Accept-Encoding: gzip X-Forwarded-For: 198."> Install Whoami :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/portable-docker/set-up-raspberry-pi/set-up-networking/index.html b/portable-docker/set-up-raspberry-pi/set-up-networking/index.html index b0d9ce096..c34646949 100644 --- a/portable-docker/set-up-raspberry-pi/set-up-networking/index.html +++ b/portable-docker/set-up-raspberry-pi/set-up-networking/index.html @@ -25,17 +25,17 @@ Run this on the Raspberry Pi sudo raspi-config Enter System Options. Enter S1 Wireless LAN. Choose your current country. Enter the SSID (Wi-Fi network name) you wish to connect to. Enter the network passphrase Configure DNS By default, DNS is handled via DHCP, which will probably work in the majority of cases."> Set up networking :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/portable-docker/set-up-raspberry-pi/set-up-ssh/index.html b/portable-docker/set-up-raspberry-pi/set-up-ssh/index.html index a79dc4d40..90a97afd5 100644 --- a/portable-docker/set-up-raspberry-pi/set-up-ssh/index.html +++ b/portable-docker/set-up-raspberry-pi/set-up-ssh/index.html @@ -29,17 +29,17 @@ Docker == root == pi SSH is used here almost like sudo. The pi user should be treated with the same respect as the root user, as it will be granted full root access through SSH (to localhost)."> Set up SSH :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/publishing-with-org-mode/building-locally/index.html b/publishing-with-org-mode/building-locally/index.html index c52ccc9c4..d4c2ab163 100644 --- a/publishing-with-org-mode/building-locally/index.html +++ b/publishing-with-org-mode/building-locally/index.html @@ -37,17 +37,17 @@ [bash]: Run this on your workstation: ## This builds the entire site, and then runs the live reload server: make serve "> Building locally :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/publishing-with-org-mode/dependencies/index.html b/publishing-with-org-mode/dependencies/index.html index c8b7e88cd..c496f976a 100644 --- a/publishing-with-org-mode/dependencies/index.html +++ b/publishing-with-org-mode/dependencies/index.html @@ -29,17 +29,17 @@ To build locally, you must install Emacs (29+), and hugo (v0.120+), using your package manager, or by downloading directly from their respective project pages. Please be aware that hugo has two editions: standard and extended, and this build requires the extended edition (TODO: verify this - I had some problems before - but maybe they are resolved - I am still using the extended edition for now)."> Dependencies :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/publishing-with-org-mode/examples/deeply/index.html b/publishing-with-org-mode/examples/deeply/index.html index e4226145d..cfc3d38f7 100644 --- a/publishing-with-org-mode/examples/deeply/index.html +++ b/publishing-with-org-mode/examples/deeply/index.html @@ -21,17 +21,17 @@ Example of a deeply … :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/publishing-with-org-mode/examples/deeply/nested/index.html b/publishing-with-org-mode/examples/deeply/nested/index.html index 4c053b600..eae84e82d 100644 --- a/publishing-with-org-mode/examples/deeply/nested/index.html +++ b/publishing-with-org-mode/examples/deeply/nested/index.html @@ -21,17 +21,17 @@ Nested … :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/publishing-with-org-mode/examples/deeply/nested/subchapters/subchapter1/index.html b/publishing-with-org-mode/examples/deeply/nested/subchapters/subchapter1/index.html index 6caf35733..2521846e4 100644 --- a/publishing-with-org-mode/examples/deeply/nested/subchapters/subchapter1/index.html +++ b/publishing-with-org-mode/examples/deeply/nested/subchapters/subchapter1/index.html @@ -21,17 +21,17 @@ Sub-chapter 1 :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/publishing-with-org-mode/examples/deeply/nested/subchapters/subchapter2/index.html b/publishing-with-org-mode/examples/deeply/nested/subchapters/subchapter2/index.html index 3fdc9a2bd..fa0d69174 100644 --- a/publishing-with-org-mode/examples/deeply/nested/subchapters/subchapter2/index.html +++ b/publishing-with-org-mode/examples/deeply/nested/subchapters/subchapter2/index.html @@ -21,17 +21,17 @@ Sub-chapter 2 :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/publishing-with-org-mode/examples/deeply/nested/subchapters/subchapter3/index.html b/publishing-with-org-mode/examples/deeply/nested/subchapters/subchapter3/index.html index d14a7616b..46bc9e2bc 100644 --- a/publishing-with-org-mode/examples/deeply/nested/subchapters/subchapter3/index.html +++ b/publishing-with-org-mode/examples/deeply/nested/subchapters/subchapter3/index.html @@ -21,17 +21,17 @@ Sub-chapter 3 :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/publishing-with-org-mode/examples/index.html b/publishing-with-org-mode/examples/index.html index 049dca6ad..57f3b3152 100644 --- a/publishing-with-org-mode/examples/index.html +++ b/publishing-with-org-mode/examples/index.html @@ -29,17 +29,17 @@ Example Org / Hugo content :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/publishing-with-org-mode/examples/org-blocks/index.html b/publishing-with-org-mode/examples/org-blocks/index.html index 1687bc024..654bf6cf3 100644 --- a/publishing-with-org-mode/examples/org-blocks/index.html +++ b/publishing-with-org-mode/examples/org-blocks/index.html @@ -45,17 +45,17 @@ This content is hidden by default."> Example Org Blocks :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/publishing-with-org-mode/examples/shortcodes/index.html b/publishing-with-org-mode/examples/shortcodes/index.html index 16645a873..6413490ec 100644 --- a/publishing-with-org-mode/examples/shortcodes/index.html +++ b/publishing-with-org-mode/examples/shortcodes/index.html @@ -29,17 +29,17 @@ Badges 1.0.0 99,999 867-5309 Email me@example.com Docs Dumpster Fire Buttons d."> Example Shortcodes :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - + + - - - - - - - - - - - - + + + + + + + + + + + + - + - - + + - + diff --git a/publishing-with-org-mode/index.html b/publishing-with-org-mode/index.html index 7860a7b6e..e7d4c03a2 100644 --- a/publishing-with-org-mode/index.html +++ b/publishing-with-org-mode/index.html @@ -25,17 +25,17 @@ Publishing with org-mode :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/publishing-with-org-mode/org-mode-emacs/editing-org-mode/index.html b/publishing-with-org-mode/org-mode-emacs/editing-org-mode/index.html index 118a55f71..ce132c49a 100644 --- a/publishing-with-org-mode/org-mode-emacs/editing-org-mode/index.html +++ b/publishing-with-org-mode/org-mode-emacs/editing-org-mode/index.html @@ -25,17 +25,17 @@ Type the link text. Navigate point to the last character of the link text. Press C-SPC (Control Spacebar) to mark the position. Navigate point to the first character of the link text. The link text should now be selected. Press C-c o i (or M-x org-insert-link). Enter the hyperlink URL. Absolute URLs should start with https://."> Editing Org-mode files :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/publishing-with-org-mode/org-mode-emacs/index.html b/publishing-with-org-mode/org-mode-emacs/index.html index fde3cad73..a01d0a5c9 100644 --- a/publishing-with-org-mode/org-mode-emacs/index.html +++ b/publishing-with-org-mode/org-mode-emacs/index.html @@ -29,17 +29,17 @@ Using Org-mode and Emacs :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/publishing-with-org-mode/org-mode-emacs/navigating-org-mode/index.html b/publishing-with-org-mode/org-mode-emacs/navigating-org-mode/index.html index 801d478a9..00f69072f 100644 --- a/publishing-with-org-mode/org-mode-emacs/navigating-org-mode/index.html +++ b/publishing-with-org-mode/org-mode-emacs/navigating-org-mode/index.html @@ -25,17 +25,17 @@ Press C-s (or M-x isearch-forward) Of course, you might not always know the exact text (or it might not be unique enough to take you right there), so its useful to know some other ways of navigating Org documents."> Navigating Org-mode files :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/publishing-with-org-mode/publish-with-github-pages/index.html b/publishing-with-org-mode/publish-with-github-pages/index.html index 8c7f7ce57..99669f61b 100644 --- a/publishing-with-org-mode/publish-with-github-pages/index.html +++ b/publishing-with-org-mode/publish-with-github-pages/index.html @@ -21,17 +21,17 @@ Publishing with GitHub pages :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/publishing-with-org-mode/publish-with-sftp/index.html b/publishing-with-org-mode/publish-with-sftp/index.html index 500f134e0..fddd79adb 100644 --- a/publishing-with-org-mode/publish-with-sftp/index.html +++ b/publishing-with-org-mode/publish-with-sftp/index.html @@ -37,17 +37,17 @@ [bash]: Run this on your workstation: rclone config Follow the prompts to setup your SFTP remote, or you can see the example SFTP documentation for doing this."> Publishing with SFTP :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/search.html b/search.html index f8e6639cc..7a2570047 100644 --- a/search.html +++ b/search.html @@ -29,17 +29,17 @@ Search :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + diff --git a/sitemap.xml b/sitemap.xml index a5e4644c1..b22221cf6 100644 --- a/sitemap.xml +++ b/sitemap.xml @@ -102,6 +102,9 @@ https://book.rymcg.tech/portable-docker/install-core-services/traefik-forward-auth/index.html + + https://book.rymcg.tech/portable-docker/install-core-services/postfix-relay/index.html + https://book.rymcg.tech/publishing-with-org-mode/index.html diff --git a/tags/index.html b/tags/index.html index d7aed54b8..9d201669c 100644 --- a/tags/index.html +++ b/tags/index.html @@ -17,17 +17,17 @@ Tags :: book.rymcg.tech - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + +