From 9cdc99b4f2f0c966de4c8ce9c0a5ae254518aaa7 Mon Sep 17 00:00:00 2001 From: Rich Kreider Date: Sun, 29 Mar 2026 22:17:22 -0400 Subject: [PATCH] initial --- .hugo_build.lock | 0 archetypes/default.md | 5 + build.sh | 8 + content/_index.md | 2 + content/posts/2019_setup.exe_switches.md | 82 ++++ content/posts/hello.md | 5 + content/posts/job_history_email.mdwn | 381 ++++++++++++++++ content/posts/wireguard.mdwn | 412 ++++++++++++++++++ hugo.toml | 78 ++++ ...s_3d8be35fd0793eabe59c88efeab77a53.content | 1 + ...scss_3d8be35fd0793eabe59c88efeab77a53.json | 1 + themes/dead-simple | 1 + themes/default/archetypes/default.md | 5 + .../default/assets/css/components/footer.css | 4 + .../default/assets/css/components/header.css | 4 + themes/default/assets/css/main.css | 34 ++ themes/default/assets/js/main.js | 1 + themes/default/content/_index.md | 9 + themes/default/content/posts/_index.md | 7 + themes/default/content/posts/post-1.md | 10 + themes/default/content/posts/post-2.md | 10 + .../content/posts/post-3/bryce-canyon.jpg | Bin 0 -> 19224 bytes themes/default/content/posts/post-3/index.md | 12 + themes/default/hugo.toml | 24 + themes/default/layouts/_partials/footer.html | 1 + themes/default/layouts/_partials/head.html | 5 + .../default/layouts/_partials/head/css.html | 15 + themes/default/layouts/_partials/head/js.html | 15 + themes/default/layouts/_partials/header.html | 2 + themes/default/layouts/_partials/menu.html | 51 +++ themes/default/layouts/_partials/terms.html | 23 + themes/default/layouts/baseof.html | 17 + themes/default/layouts/home.html | 9 + themes/default/layouts/page.html | 10 + themes/default/layouts/section.html | 10 + themes/default/layouts/taxonomy.html | 7 + themes/default/layouts/term.html | 7 + themes/default/static/favicon.ico | Bin 0 -> 15406 bytes themes/nsp | 1 + themes/rustic/archetypes/default.md | 5 + .../rustic/assets/css/components/footer.css | 4 + .../rustic/assets/css/components/header.css | 4 + themes/rustic/assets/css/main.css | 15 + themes/rustic/assets/js/main.js | 1 + themes/rustic/content/_index.md | 9 + themes/rustic/content/posts/_index.md | 7 + themes/rustic/content/posts/post-1.md | 10 + themes/rustic/content/posts/post-2.md | 10 + .../content/posts/post-3/bryce-canyon.jpg | Bin 0 -> 19224 bytes themes/rustic/content/posts/post-3/index.md | 12 + themes/rustic/hugo.toml | 24 + themes/rustic/layouts/_partials/footer.html | 1 + themes/rustic/layouts/_partials/head.html | 5 + themes/rustic/layouts/_partials/head/css.html | 15 + themes/rustic/layouts/_partials/head/js.html | 15 + themes/rustic/layouts/_partials/header.html | 2 + themes/rustic/layouts/_partials/menu.html | 51 +++ themes/rustic/layouts/_partials/terms.html | 23 + themes/rustic/layouts/baseof.html | 17 + themes/rustic/layouts/home.html | 9 + themes/rustic/layouts/page.html | 10 + themes/rustic/layouts/section.html | 10 + themes/rustic/layouts/taxonomy.html | 7 + themes/rustic/layouts/term.html | 7 + themes/rustic/static/favicon.ico | Bin 0 -> 15406 bytes themes/trainsh | 1 + 66 files changed, 1543 insertions(+) create mode 100644 .hugo_build.lock create mode 100644 archetypes/default.md create mode 100755 build.sh create mode 100644 content/_index.md create mode 100644 content/posts/2019_setup.exe_switches.md create mode 100644 content/posts/hello.md create mode 100644 content/posts/job_history_email.mdwn create mode 100644 content/posts/wireguard.mdwn create mode 100644 hugo.toml create mode 100644 resources/_gen/assets/css/main.scss_3d8be35fd0793eabe59c88efeab77a53.content create mode 100644 resources/_gen/assets/css/main.scss_3d8be35fd0793eabe59c88efeab77a53.json create mode 160000 themes/dead-simple create mode 100644 themes/default/archetypes/default.md create mode 100644 themes/default/assets/css/components/footer.css create mode 100644 themes/default/assets/css/components/header.css create mode 100644 themes/default/assets/css/main.css create mode 100644 themes/default/assets/js/main.js create mode 100644 themes/default/content/_index.md create mode 100644 themes/default/content/posts/_index.md create mode 100644 themes/default/content/posts/post-1.md create mode 100644 themes/default/content/posts/post-2.md create mode 100644 themes/default/content/posts/post-3/bryce-canyon.jpg create mode 100644 themes/default/content/posts/post-3/index.md create mode 100644 themes/default/hugo.toml create mode 100644 themes/default/layouts/_partials/footer.html create mode 100644 themes/default/layouts/_partials/head.html create mode 100644 themes/default/layouts/_partials/head/css.html create mode 100644 themes/default/layouts/_partials/head/js.html create mode 100644 themes/default/layouts/_partials/header.html create mode 100644 themes/default/layouts/_partials/menu.html create mode 100644 themes/default/layouts/_partials/terms.html create mode 100644 themes/default/layouts/baseof.html create mode 100644 themes/default/layouts/home.html create mode 100644 themes/default/layouts/page.html create mode 100644 themes/default/layouts/section.html create mode 100644 themes/default/layouts/taxonomy.html create mode 100644 themes/default/layouts/term.html create mode 100644 themes/default/static/favicon.ico create mode 160000 themes/nsp create mode 100644 themes/rustic/archetypes/default.md create mode 100644 themes/rustic/assets/css/components/footer.css create mode 100644 themes/rustic/assets/css/components/header.css create mode 100644 themes/rustic/assets/css/main.css create mode 100644 themes/rustic/assets/js/main.js create mode 100644 themes/rustic/content/_index.md create mode 100644 themes/rustic/content/posts/_index.md create mode 100644 themes/rustic/content/posts/post-1.md create mode 100644 themes/rustic/content/posts/post-2.md create mode 100644 themes/rustic/content/posts/post-3/bryce-canyon.jpg create mode 100644 themes/rustic/content/posts/post-3/index.md create mode 100644 themes/rustic/hugo.toml create mode 100644 themes/rustic/layouts/_partials/footer.html create mode 100644 themes/rustic/layouts/_partials/head.html create mode 100644 themes/rustic/layouts/_partials/head/css.html create mode 100644 themes/rustic/layouts/_partials/head/js.html create mode 100644 themes/rustic/layouts/_partials/header.html create mode 100644 themes/rustic/layouts/_partials/menu.html create mode 100644 themes/rustic/layouts/_partials/terms.html create mode 100644 themes/rustic/layouts/baseof.html create mode 100644 themes/rustic/layouts/home.html create mode 100644 themes/rustic/layouts/page.html create mode 100644 themes/rustic/layouts/section.html create mode 100644 themes/rustic/layouts/taxonomy.html create mode 100644 themes/rustic/layouts/term.html create mode 100644 themes/rustic/static/favicon.ico create mode 160000 themes/trainsh diff --git a/.hugo_build.lock b/.hugo_build.lock new file mode 100644 index 0000000..e69de29 diff --git a/archetypes/default.md b/archetypes/default.md new file mode 100644 index 0000000..25b6752 --- /dev/null +++ b/archetypes/default.md @@ -0,0 +1,5 @@ ++++ +date = '{{ .Date }}' +draft = true +title = '{{ replace .File.ContentBaseName "-" " " | title }}' ++++ diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..dcc947c --- /dev/null +++ b/build.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +echo Building... + +hugo --gc --minify -s /srv/www/kreider.io/hugo_source + +chown www-data:www-data -R /srv/www/kreider.io/web + diff --git a/content/_index.md b/content/_index.md new file mode 100644 index 0000000..a845151 --- /dev/null +++ b/content/_index.md @@ -0,0 +1,2 @@ +--- +--- diff --git a/content/posts/2019_setup.exe_switches.md b/content/posts/2019_setup.exe_switches.md new file mode 100644 index 0000000..9f477e1 --- /dev/null +++ b/content/posts/2019_setup.exe_switches.md @@ -0,0 +1,82 @@ +--- +title: Windows Server 2019 Setup Command Line Switches +date: 2026-03-29 +toc: true +--- +## Notes + +- This table is based on Microsoft's current **Windows Setup Command-Line Options** reference and then filtered/interpreted for **Windows Server 2019 relevance**. +- Microsoft now documents these switches on a single cross-version page, so some switches on that page were introduced **after Server 2019 (1809)** shipped. +- The **Server 2019 status** column is there so you can immediately see what is likely usable on Server 2019 media versus what appears to be later-only. + +## Table + +| Switch | Syntax | What it means | Server 2019 status | +|---|---|---|---| +| `/1394Debug` | `/1394Debug: [BaudRate:]` | Enables kernel debugging over IEEE 1394 / FireWire during Setup and Windows PE. | Likely supported | +| `/AddBootMgrLast` | `/AddBootMgrLast` | Adds Windows Boot Manager as the last UEFI boot entry. | Likely supported | +| `/Auto` | `/Auto {Clean \| DataOnly \| Upgrade}` | Runs Setup in automated mode for clean install, data-only migration, or upgrade. | Supported | +| `/BitLocker` | `/BitLocker {AlwaysSuspend \| TryKeepActive \| ForceKeepActive}` | Controls how Setup handles BitLocker during upgrades. | Supported | +| `/BusParams` | `/BusParams:` | Specifies the PCI address for a debug port device. | Likely supported | +| `/Compat` | `/Compat {IgnoreWarning \| ScanOnly}` | Controls compatibility scans and whether warnings are ignored or only scanned. | Supported | +| `/CompactOS` | `/CompactOS {Enable \| Disable}` | Tells Setup whether to use Compact OS compression. | Likely supported | +| `/ConfigFile` | `/ConfigFile:` | Points Setup to a `setupconfig` file. | Likely supported | +| `/CopyLogs` | `/CopyLogs ` | Copies compressed Setup logs to a local or UNC path, typically on failure. | Supported | +| `/Debug` | `/Debug: [BaudRate:]` | Enables kernel debugging over a COM port during Setup and Windows PE. | Likely supported | +| `/DiagnosticPrompt` | `/DiagnosticPrompt {Enable \| Disable}` | Enables or disables `Shift+F10` command prompt access during Setup. | Supported | +| `/DynamicUpdate` | `/DynamicUpdate {Enable \| Disable \| NoDrivers \| NoLCU \| NoDriversNoLCU}` | Controls Setup Dynamic Update behavior. | Base switch supported; `NoDrivers` / `NoLCU` / `NoDriversNoLCU` were added later than Server 2019 | +| `/EMSPort` | `/EMSPort:{COM1 \| COM2 \| UseBIOSSettings \| Off} [/EMSBaudRate:]` | Enables or disables Emergency Management Services during Setup. | Likely supported | +| `/EULA` | `/EULA accept` | Pre-accepts the Windows Setup EULA. | Not a Server 2019 switch; added for Windows 11 | +| `/Finalize` | `/Finalize` | Finishes a previously started update operation and reboots into offline phase. | Not Server 2019-era; added in Windows 10 version 2004 | +| `/ImageIndex` | `/ImageIndex ` | Forces Setup to use a specific image index from `install.wim`. | Probably not Server 2019-era; documented as added in Windows 10 version 2004 | +| `/InstallDrivers` | `/InstallDrivers ` | Adds `.inf` drivers from a folder during installation/upgrade. | Supported | +| `/InstallFrom` | `/InstallFrom ` | Uses an alternate `.wim` or split `.swm` image file instead of the default `install.wim`. | Likely supported | +| `/InstallLangPacks` | `/InstallLangPacks ` | Adds language packs and related language capabilities from `.cab` files. | Supported | +| `/m` | `/m:` | Uses alternate replacement files from another folder, checking that folder before default sources. | Legacy but likely supported in Setup media scenarios | +| `/MigrateDrivers` | `/MigrateDrivers {All \| None}` | Controls whether drivers from the existing installation are migrated during upgrade. | Supported | +| `/NetDebug` | `/NetDebug:hostip=,port=,key=[,nodhcp][,busparams=]` | Enables kernel debugging over the network. | Likely supported | +| `/NoReboot` | `/NoReboot` | Prevents the automatic reboot after the down-level phase finishes. | Supported | +| `/PKey` | `/PKey ` | Supplies a product key to Setup. | Supported | +| `/PostOOBE` | `/PostOOBE ` | Runs `setupcomplete.cmd` after Setup completes / after OOBE. | Supported | +| `/PostRollback` | `/PostRollback [/PostRollbackContext {system \| user}]` | Runs `setuprollback.cmd` after rollback from a failed upgrade or uninstall. | Supported; `/PostRollbackContext` is also Server 2019-era | +| `/Priority` | `/Priority {Normal \| Low}` | Changes Setup thread priority. | Supported | +| `/Quiet` | `/Quiet` | Suppresses the Setup UI. | Supported | +| `/ReflectDrivers` | `/ReflectDrivers ` | Points Setup to third-party encryption drivers that must be reflected into the new OS. | Supported | +| `/ResizeRecoveryPartition` | `/ResizeRecoveryPartition {Enable \| Disable}` | Allows or blocks resizing/creating the Windows RE partition during install. | Likely supported | +| `/ShowOOBE` | `/ShowOOBE {Full \| None}` | Controls whether OOBE is shown interactively. | Supported | +| `/SkipFinalize` | `/SkipFinalize` | Starts update operations without starting the reboot into offline phase. | Not Server 2019-era; added in Windows 10 version 2004 | +| `/Telemetry` | `/Telemetry {Enable \| Disable}` | Controls whether Setup captures and reports installation data. | Supported | +| `/TempDrive` | `/TempDrive ` | Uses a specific partition for temporary installation files. | Supported | +| `/Unattend` | `/Unattend:` | Uses an unattend XML answer file. | Supported | +| `/Uninstall` | `/Uninstall {Enable \| Disable}` | Controls whether rollback/go-back controls are retained. | Supported | +| `/USBDebug` | `/USBDebug:` | Sets up debugging on a USB port. | Likely supported | +| `/WDSDiscover` | `/WDSDiscover` | Puts the Windows Deployment Services client in discover mode. | Supported for Server 2019-era WinPE/WDS use | +| `/WDSServer` | `/WDSServer:` | Tells the WDS client which WDS server to contact. | Supported for Server 2019-era WinPE/WDS use | + +## Practical takeaways for Windows Server 2019 + +- For normal **in-place upgrades/repair installs** on Server 2019, the switches you're most likely to care about are: + - `/Auto` + - `/Compat` + - `/CopyLogs` + - `/DynamicUpdate` + - `/InstallDrivers` + - `/MigrateDrivers` + - `/NoReboot` + - `/PKey` + - `/Quiet` + - `/ReflectDrivers` + - `/TempDrive` +- For **unattended clean installs**, the big one is: + - `/Unattend` +- For **debugging/troubleshooting Setup**, the important ones are: + - `/CopyLogs` + - `/DiagnosticPrompt` + - `/Debug` + - `/NetDebug` + - `/USBDebug` + - `/1394Debug` + +## Source basis + +Compiled from Microsoft Learn's Windows Setup command-line reference, with version notes mapped back to what is and is not Server 2019-era behavior. diff --git a/content/posts/hello.md b/content/posts/hello.md new file mode 100644 index 0000000..6a5edc7 --- /dev/null +++ b/content/posts/hello.md @@ -0,0 +1,5 @@ +--- +title: Hello, world. +date: 2026-03-27 +--- +Hello world. diff --git a/content/posts/job_history_email.mdwn b/content/posts/job_history_email.mdwn new file mode 100644 index 0000000..2c593a8 --- /dev/null +++ b/content/posts/job_history_email.mdwn @@ -0,0 +1,381 @@ +# SQL Server: Daily Failed SQL Job Email Report + +This guide sets up: + +- Database Mail +- a Database Mail profile +- a stored procedure that emails failed SQL Agent jobs from the last 24 hours +- a SQL Agent job scheduled for **11:59 PM daily** + +--- + +## What this does + +Every night at **11:59 PM**, SQL Server Agent runs a stored procedure in `msdb` that: + +- checks SQL Agent job history for failed jobs in the last 24 hours +- emails the failed job names, failure time, duration, and failure reason +- sends a "no failures" email if nothing failed + +--- + +## Prerequisites + +You need: + +- SQL Server Agent running +- an SMTP server you can relay through +- the following SMTP details: + - SMTP server name + - SMTP port + - whether SSL/TLS is required + - SMTP username/password if authentication is required + - From address + - recipient email address + +--- + +## Step 1: Enable Database Mail XPs + +Run this first: + +```sql +EXEC sp_configure 'show advanced options', 1; +RECONFIGURE; + +EXEC sp_configure 'Database Mail XPs', 1; +RECONFIGURE; +``` + +--- + +## Step 2: Create the Database Mail account and profile + +Replace the sample values below. + +### Variables you should replace + +- `SQLAlerts` = mail profile name +- `SQLAlertsAccount` = mail account name +- `smtp.yourdomain.com` = SMTP server +- `587` = SMTP port +- `sqlalerts@yourdomain.com` = From address +- `SQL Alerts` = display name +- `smtp-user` = SMTP username +- `smtp-password` = SMTP password + +### Script + +```sql +USE msdb; +GO + +-- Create Database Mail account +EXEC dbo.sysmail_add_account_sp + @account_name = N'SQLAlertsAccount', + @description = N'SQL Server Database Mail account for alerts', + @email_address = N'sqlalerts@yourdomain.com', + @display_name = N'SQL Alerts', + @replyto_address = N'sqlalerts@yourdomain.com', + @mailserver_name = N'smtp.yourdomain.com', + @port = 587, + @enable_ssl = 1, + @username = N'smtp-user', + @password = N'smtp-password'; +GO + +-- Create Database Mail profile +EXEC dbo.sysmail_add_profile_sp + @profile_name = N'SQLAlerts', + @description = N'Database Mail profile for SQL alerting'; +GO + +-- Add account to profile +EXEC dbo.sysmail_add_profileaccount_sp + @profile_name = N'SQLAlerts', + @account_name = N'SQLAlertsAccount', + @sequence_number = 1; +GO + +-- Make profile public/default if desired +EXEC dbo.sysmail_add_principalprofile_sp + @profile_name = N'SQLAlerts', + @principal_name = N'public', + @is_default = 1; +GO +``` + +### Notes + +- If your SMTP server does **not** require authentication, remove `@username` and `@password`. +- If your SMTP server uses port 25 and no TLS, set: + - `@port = 25` + - `@enable_ssl = 0` +- If your mail relay only allows specific source IPs or hosts, make sure the SQL Server can relay through it. + +--- + +## Step 3: Test Database Mail + +Run this before doing anything else. + +```sql +EXEC msdb.dbo.sp_send_dbmail + @profile_name = 'SQLAlerts', + @recipients = 'you@domain.com', + @subject = 'SQL Database Mail Test', + @body = 'Database Mail is working.'; +``` + +If this fails, stop there and fix SMTP/profile/authentication first. + +--- + +## Step 4: Create the stored procedure that emails failed jobs + +Replace `you@domain.com` with the real recipient. + +```sql +USE msdb; +GO + +CREATE OR ALTER PROCEDURE dbo.usp_EmailDailyFailedJobs +AS +BEGIN + SET NOCOUNT ON; + + DECLARE @Subject nvarchar(255); + SET @Subject = N'Daily SQL Job Failures - ' + @@SERVERNAME; + + IF EXISTS + ( + SELECT 1 + FROM msdb.dbo.sysjobhistory h + WHERE h.step_id = 0 + AND h.run_status = 0 + AND msdb.dbo.agent_datetime(h.run_date, h.run_time) >= DATEADD(DAY, -1, GETDATE()) + ) + BEGIN + EXEC msdb.dbo.sp_send_dbmail + @profile_name = 'SQLAlerts', + @recipients = 'you@domain.com', + @subject = @Subject, + @body = 'Failed SQL Agent jobs in the last 24 hours:', + @query = N' +SET NOCOUNT ON; + +SELECT + @@SERVERNAME AS ServerName, + j.name AS JobName, + msdb.dbo.agent_datetime(h.run_date, h.run_time) AS FailedAt, + STUFF(STUFF(RIGHT(''000000'' + CAST(h.run_duration AS varchar(6)), 6), 3, 0, '':''), + 6, 0, '':'') AS RunDuration_HHMMSS, + h.message AS FailureReason +FROM msdb.dbo.sysjobhistory h +JOIN msdb.dbo.sysjobs j + ON j.job_id = h.job_id +WHERE + h.step_id = 0 + AND h.run_status = 0 + AND msdb.dbo.agent_datetime(h.run_date, h.run_time) >= DATEADD(DAY, -1, GETDATE()) +ORDER BY FailedAt DESC;', + @execute_query_database = 'msdb', + @query_result_header = 1, + @query_result_separator = ' | ', + @query_result_no_padding = 1; + END + ELSE + BEGIN + EXEC msdb.dbo.sp_send_dbmail + @profile_name = 'SQLAlerts', + @recipients = 'you@domain.com', + @subject = @Subject, + @body = 'No SQL Agent job failures were recorded in the last 24 hours.'; + END +END +GO +``` + +--- + +## Step 5: Test the stored procedure manually + +```sql +EXEC msdb.dbo.usp_EmailDailyFailedJobs; +``` + +If this does not send mail, do not create the scheduled job yet. + +--- + +## Step 6: Create the SQL Agent job scheduled for 11:59 PM daily + +```sql +USE msdb; +GO + +DECLARE @job_id UNIQUEIDENTIFIER; + +-- Create the job +EXEC msdb.dbo.sp_add_job + @job_name = N'Daily SQL Job Failure Email', + @enabled = 1, + @description = N'Sends a daily email at 11:59 PM listing failed SQL Agent jobs from the last 24 hours.', + @owner_login_name = N'sa', + @job_id = @job_id OUTPUT; + +-- Add the job step +EXEC msdb.dbo.sp_add_jobstep + @job_id = @job_id, + @step_name = N'Run Failure Report', + @subsystem = N'TSQL', + @database_name = N'msdb', + @command = N'EXEC msdb.dbo.usp_EmailDailyFailedJobs;', + @on_success_action = 1, + @on_fail_action = 2; + +-- Create the schedule +EXEC msdb.dbo.sp_add_schedule + @schedule_name = N'Daily 11:59 PM', + @enabled = 1, + @freq_type = 4, + @freq_interval = 1, + @active_start_time = 235900; + +-- Attach schedule to job +EXEC msdb.dbo.sp_attach_schedule + @job_id = @job_id, + @schedule_name = N'Daily 11:59 PM'; + +-- Attach job to local server +EXEC msdb.dbo.sp_add_jobserver + @job_id = @job_id, + @server_name = N'(LOCAL)'; +GO +``` + +--- + +## Step 7: Test the SQL Agent job immediately + +Do not wait until midnight to find out it is broken. + +```sql +EXEC msdb.dbo.sp_start_job + @job_name = 'Daily SQL Job Failure Email'; +``` + +--- + +## Step 8: Check job history + +```sql +EXEC msdb.dbo.sp_help_jobhistory + @job_name = 'Daily SQL Job Failure Email'; +``` + +--- + +## Helpful verification queries + +### Show mail profiles + +```sql +SELECT name, description +FROM msdb.dbo.sysmail_profile; +``` + +### Show which account is tied to which profile + +```sql +SELECT + p.name AS ProfileName, + a.name AS AccountName, + a.email_address, + a.display_name, + s.servername, + s.port +FROM msdb.dbo.sysmail_profile p +JOIN msdb.dbo.sysmail_profileaccount pa + ON p.profile_id = pa.profile_id +JOIN msdb.dbo.sysmail_account a + ON pa.account_id = a.account_id +JOIN msdb.dbo.sysmail_server s + ON a.account_id = s.account_id; +``` + +### Show public/default profiles + +```sql +SELECT + p.name, + pp.is_default, + pp.principal_id +FROM msdb.dbo.sysmail_principalprofile pp +JOIN msdb.dbo.sysmail_profile p + ON pp.profile_id = p.profile_id; +``` + +### Show mail log/errors + +```sql +SELECT * +FROM msdb.dbo.sysmail_event_log +ORDER BY log_date DESC; +``` + +### Show unsent/sent/failed messages + +```sql +SELECT * +FROM msdb.dbo.sysmail_allitems +ORDER BY send_request_date DESC; +``` + +--- + +## Common failure points + +### 1. `sp_send_dbmail` fails +Usually one of these: + +- wrong profile name +- bad SMTP server/port +- auth failure +- relay denied +- TLS/SSL mismatch +- firewall blocking outbound SMTP + +### 2. Job never runs +Usually one of these: + +- SQL Server Agent service is stopped +- schedule was not attached +- job is disabled + +### 3. Stored procedure compiles but sends nothing +Usually one of these: + +- there were no failed jobs in the last 24 hours +- recipient email is wrong +- mail profile is wrong + +--- + +## Blunt recommendation + +Build and test in this order: + +1. enable Database Mail XPs +2. create account/profile +3. test `sp_send_dbmail` +4. create stored procedure +5. run stored procedure manually +6. create Agent job/schedule +7. manually start Agent job +8. trust the 11:59 PM schedule only after the manual test works + +If step 3 fails, everything after it is pointless until SMTP is fixed. + + +[[!tag notes mssql]] diff --git a/content/posts/wireguard.mdwn b/content/posts/wireguard.mdwn new file mode 100644 index 0000000..57a25fc --- /dev/null +++ b/content/posts/wireguard.mdwn @@ -0,0 +1,412 @@ +# WireGuard VPN Setup on Debian 13 + +Clean, minimal, self-hosted WireGuard setup with: + +- Full tunnel support +- NAT for internet access +- Multi-user capability +- Per-user access control via firewall + +--- + +## 0. Assumptions + +- Public interface: `eth0` +- VPN subnet: `10.10.10.0/24` +- Server is publicly reachable + +Replace `eth0` with your real interface name if needed, such as `ens18`, `ens3`, or `enp1s0`. + +--- + +## 1. Install WireGuard + +``` +apt update +apt install wireguard +``` + +--- + +## 2. Enable IP Forwarding + +``` +sysctl -w net.ipv4.ip_forward=1 +``` + +Persist it: + +``` +echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf +sysctl -p +``` + +--- + +## 3. Generate Keys + +``` +cd /etc/wireguard + +wg genkey | tee server.key | wg pubkey > server.pub +wg genkey | tee client.key | wg pubkey > client.pub + +chmod 600 *.key +``` + +--- + +## 4. Server Configuration + +Create: + +``` +nano /etc/wireguard/wg0.conf +``` + +``` +[Interface] +Address = 10.10.10.1/24 +PrivateKey = +ListenPort = 51820 + +# NAT + forwarding +PostUp = iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE +PostUp = iptables -A FORWARD -i wg0 -j ACCEPT +PostUp = iptables -A FORWARD -o wg0 -j ACCEPT + +PostDown = iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE +PostDown = iptables -D FORWARD -i wg0 -j ACCEPT +PostDown = iptables -D FORWARD -o wg0 -j ACCEPT + +[Peer] +PublicKey = +AllowedIPs = 10.10.10.2/32 +``` + +Notes: + +- `Address = 10.10.10.1/24` is the server's VPN IP. +- `AllowedIPs = 10.10.10.2/32` means that client owns only `10.10.10.2`. +- Do not reuse keys between devices. + +--- + +## 5. Start WireGuard + +``` +wg-quick up wg0 +systemctl enable wg-quick@wg0 +``` + +Check status: + +``` +wg show +ip addr show wg0 +``` + +--- + +## 6. Client Configuration + +Use this on Windows, Linux, or macOS: + +``` +[Interface] +Address = 10.10.10.2/24 +PrivateKey = +DNS = 1.1.1.1 + +[Peer] +PublicKey = +Endpoint = YOUR_SERVER_IP:51820 +AllowedIPs = 0.0.0.0/0 +PersistentKeepalive = 25 +``` + +Notes: + +- `AllowedIPs = 0.0.0.0/0` sends all client traffic through the VPN. + +- If you only want access to specific private networks, replace `0.0.0.0/0` with those subnets. + +Example split tunnel: + +``` +AllowedIPs = 10.10.10.0/24, 192.168.50.0/24 +``` + +--- + +## 7. Open Firewall Port + +If using UFW: + +``` +ufw allow 51820/udp +``` + +Or raw iptables: + +``` +iptables -A INPUT -p udp --dport 51820 -j ACCEPT +``` + +--- + +## 8. Test Connection + +From the client: + +``` +curl ip.me +``` + +Expected result: + +- If full tunnel is enabled, this should show the server's public IP. + +Also test: + +``` +ping 10.10.10.1 +``` + +--- + +## 9. Add Additional Users + +Generate new keys: + +``` +wg genkey | tee user2.key | wg pubkey > user2.pub +chmod 600 user2.key +``` + +Add to server config: + +``` +[Peer] +PublicKey = +AllowedIPs = 10.10.10.3/32 +``` + +Apply changes: + +``` +wg syncconf wg0 <(wg-quick strip wg0) +``` + +Client config example for user2: + +``` +[Interface] +Address = 10.10.10.3/24 +PrivateKey = +DNS = 1.1.1.1 + +[Peer] +PublicKey = +Endpoint = YOUR_SERVER_IP:51820 +AllowedIPs = 0.0.0.0/0 +PersistentKeepalive = 25 +``` + +--- + +## 10. Access Control and Network Design + +WireGuard handles authentication by key. + +WireGuard does **not** decide what a connected peer is allowed to reach. +That is handled by your firewall, typically with `iptables` or `nftables`. + +Think of it like this: + +- WireGuard key + peer IP = identity +- Firewall rules = authorization + +### Important + +The examples below use: + +- `10.10.10.2` = full access user +- `10.10.10.3` = restricted user +- `10.10.10.4` = internet-only user + +Adjust these to your actual peer IP assignments. + +--- + +### Scenario A: Public server only, no private networks behind it + +This is the simplest case. + +The server only has: + +- `eth0` facing the internet +- `wg0` for VPN clients + +There is no LAN behind the server. You just want clients to: + +- connect to the server +- route internet traffic through it +- maybe reach services running on the server itself + +#### Full tunnel user + +``` +iptables -A FORWARD -i wg0 -s 10.10.10.2 -o eth0 -j ACCEPT +iptables -A FORWARD -o wg0 -d 10.10.10.2 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT +``` + +#### Internet-only restricted user + +``` +iptables -A FORWARD -i wg0 -s 10.10.10.4 -o eth0 -j ACCEPT +iptables -A FORWARD -o wg0 -d 10.10.10.4 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT +iptables -A FORWARD -i wg0 -s 10.10.10.4 -j DROP +``` + +That last rule says: + +- allow that peer out to the internet +- drop any other forwarded access attempt + +If the user also needs to reach services hosted directly on the VPN server itself, that is controlled by `INPUT` rules, not `FORWARD`. + +Example: allow SSH from one VPN peer to the server: + +``` +iptables -A INPUT -i wg0 -s 10.10.10.3 -p tcp --dport 22 -j ACCEPT +``` + +Example: block all other VPN clients from SSH to the server: + +``` +iptables -A INPUT -i wg0 -p tcp --dport 22 -j DROP +``` + +--- + +### Scenario B: Server has private networks behind it + +Use this if the Debian server can route to private networks such as: + +- `192.168.1.0/24` +- `10.0.0.0/24` +- `172.16.50.0/24` + +In this case, your VPN clients can be selectively allowed to those networks. + +#### Full access user to all routed private networks + +``` +iptables -A FORWARD -i wg0 -s 10.10.10.2 -j ACCEPT +``` + +That is broad. It allows that peer to anything the server can route to. + +#### Restricted user to a single host + +Example: only allow `10.10.10.3` to reach `192.168.1.50` + +``` +iptables -A FORWARD -i wg0 -s 10.10.10.3 -d 192.168.1.50 -j ACCEPT +iptables -A FORWARD -i wg0 -s 10.10.10.3 -j DROP +``` + +#### Restricted user to a whole subnet + +Example: only allow `10.10.10.3` to reach `192.168.1.0/24` + +``` +iptables -A FORWARD -i wg0 -s 10.10.10.3 -d 192.168.1.0/24 -j ACCEPT +iptables -A FORWARD -i wg0 -s 10.10.10.3 -j DROP +``` + +#### Internet plus one private subnet + +Example: allow `10.10.10.3` to: + +- use the server as an internet gateway +- access `192.168.1.0/24` +- nothing else + +``` +iptables -A FORWARD -i wg0 -s 10.10.10.3 -d 192.168.1.0/24 -j ACCEPT +iptables -A FORWARD -i wg0 -s 10.10.10.3 -o eth0 -j ACCEPT +iptables -A FORWARD -o wg0 -d 10.10.10.3 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT +iptables -A FORWARD -i wg0 -s 10.10.10.3 -j DROP +``` + +#### Client-side route restriction + +You should also tighten the client config. + +If a peer should only reach one private subnet, do not send all traffic through the tunnel. + +Example client config: + +``` +AllowedIPs = 10.10.10.0/24, 192.168.1.0/24 +``` + +That gives split-tunnel access only to: + +- the VPN subnet +- the private subnet behind the server + +--- + +## 11. Remove or Revoke Access + +Remove a peer immediately: + +``` +wg set wg0 peer remove +``` + +Or edit `wg0.conf` and reload: + +``` +wg syncconf wg0 <(wg-quick strip wg0) +``` + +--- + +## 12. Common Issues + +- IP forwarding not enabled +- Wrong public interface name +- Firewall blocking UDP 51820 +- NAT rule missing +- Server not publicly reachable +- Client `AllowedIPs` too broad or too narrow +- Client clock wildly wrong +- Forgot `PersistentKeepalive = 25` for clients behind NAT + +--- + +## 13. Key Concepts + +- Each peer should have its own keypair +- No passwords or usernames in WireGuard +- One device should not share another device's key +- VPN peer IPs should be treated like identities +- Firewall rules decide what each peer can reach + +--- + +## 14. Recommended Next Step + +This walkthrough uses `iptables` because it is straightforward and familiar. + +For a cleaner long-term setup on Debian 13, consider moving the policy to `nftables`, especially if you will have: + +- multiple users +- different access classes +- persistent firewall rules you want managed sanely + +[[!tag wireguard debian linux vpn]] diff --git a/hugo.toml b/hugo.toml new file mode 100644 index 0000000..dcc542a --- /dev/null +++ b/hugo.toml @@ -0,0 +1,78 @@ +baseURL = 'https://example.org/' +locale = 'en-us' +title = 'Rich Kreider' +theme = 'dead-simple' +publishDir = '/srv/www/kreider.io/web' +cleanDestinationDir = true +disableHugoGeneratorInject = true + +enableGitInfo = true + +[[menu.main]] +name = "Home" +url = "/" +weight = 1 + +[[menu.main]] +name = "Tags" +url = "https://hugo-dead-simple.netlify.com/tags" +weight = 3 + +#[markup.highlight] +#codeFences = true +#style = "bw" +#lineNumbersInTable = false +#noClasses = false + +[markup.goldmark.extensions.passthrough] +enable = true + + [markup.goldmark.extensions.passthrough.delimiters] + block = [ [ "\\[", "\\]" ], [ "$$", "$$" ] ] + inline = [ [ "\\(", "\\)" ] ] + +[markup.goldmark.renderer] +unsafe = true + +[outputs] +home = ["HTML"] + +[extra] + list_pages = true + +[markup] + [markup.goldmark] + [markup.goldmark.parser] + [markup.goldmark.parser.attribute] + block = true + title = true + + [markup.highlight] + anchorLineNos = false + codeFences = true + guessSyntax = false + hl_Lines = '' + hl_inline = false + lineAnchors = '' + lineNoStart = 1 + lineNos = false + lineNumbersInTable = true + noClasses = true + noHl = false + style = 'rrt' + tabWidth = 4 + + [markup.tableOfContents] + startLevel = 2 + endLevel = 3 + ordered = false + +[params] +description = "FOO" +noSearch = false + [params.theme_config] + appearance = "auto" + back_home_text = "~/home" + date_format = "2006-01-02" + isListGroupByDate = true + isShowFooter = false diff --git a/resources/_gen/assets/css/main.scss_3d8be35fd0793eabe59c88efeab77a53.content b/resources/_gen/assets/css/main.scss_3d8be35fd0793eabe59c88efeab77a53.content new file mode 100644 index 0000000..231a148 --- /dev/null +++ b/resources/_gen/assets/css/main.scss_3d8be35fd0793eabe59c88efeab77a53.content @@ -0,0 +1 @@ +body[a="dark"]{background-color:#000;color:#fff}body[a="dark"] a{color:#79a8ff}body[a="dark"] a:visited{color:#f78fe7}body[a="dark"] details{border:thin solid #fff}body[a="dark"] details summary{color:#fff}body[a="dark"] details[open] summary{border-bottom:1px solid #fff}body[a="dark"] pre{background:#000}body[a="dark"] code:not(pre>code){background-color:#fff;color:#000}body[a="dark"] *:target{background:#2f3849;color:#fff}body[a="dark"] table,body[a="dark"] th,body[a="dark"] td{border:thin solid #fff}body[a="dark"] .toc{border:thin solid #fff;padding:1rem}body[a="dark"] figcaption{color:#000}body[a="dark"] blockquote{border:thin solid #fff}body[a="light"]{background-color:#fff;color:#000}body[a="light"] a{color:#3548cf}body[a="light"] a:visited{color:#8f0075}body[a="light"] details{border:thin solid #000}body[a="light"] details summary{color:#000}body[a="light"] details[open] summary{border-bottom:1px solid #000}body[a="light"] pre{background:#fff}body[a="light"] code:not(pre>code){background-color:#000;color:#fff}body[a="light"] *:target{background:#dae5ec;color:#000}body[a="light"] table,body[a="light"] th,body[a="light"] td{border:thin solid #000}body[a="light"] .toc{border:thin solid #000;padding:1rem}body[a="light"] figcaption{color:#595959}body[a="light"] blockquote{border:thin solid #000}@media (prefers-color-scheme: dark){body[a="auto"]{background-color:#000;color:#fff}body[a="auto"] a{color:#79a8ff}body[a="auto"] a:visited{color:#f78fe7}body[a="auto"] details{border:thin solid #fff}body[a="auto"] details summary{color:#fff}body[a="auto"] details[open] summary{border-bottom:1px solid #fff}body[a="auto"] pre{background:#000}body[a="auto"] code:not(pre>code){background-color:#fff;color:#000}body[a="auto"] *:target{background:#2f3849;color:#fff}body[a="auto"] table,body[a="auto"] th,body[a="auto"] td{border:thin solid #fff}body[a="auto"] .toc{border:thin solid #fff;padding:1rem}body[a="auto"] figcaption{color:#000}body[a="auto"] blockquote{border:thin solid #fff}}@media (prefers-color-scheme: light){body[a="auto"]{background-color:#fff;color:#000}body[a="auto"] a{color:#3548cf}body[a="auto"] a:visited{color:#8f0075}body[a="auto"] details{border:thin solid #000}body[a="auto"] details summary{color:#000}body[a="auto"] details[open] summary{border-bottom:1px solid #000}body[a="auto"] pre{background:#fff}body[a="auto"] code:not(pre>code){background-color:#000;color:#fff}body[a="auto"] *:target{background:#dae5ec;color:#000}body[a="auto"] table,body[a="auto"] th,body[a="auto"] td{border:thin solid #000}body[a="auto"] .toc{border:thin solid #000;padding:1rem}body[a="auto"] figcaption{color:#595959}body[a="auto"] blockquote{border:thin solid #000}}html{height:100%}body{font-family:monospace;font-size:16px;line-height:1.4;margin:0;min-height:100%;overflow-wrap:break-word}h2,h3,h4,h5,h6{margin-top:1.5rem}p{margin:1rem 0}li{margin:0.4rem 0}a{text-decoration:none}a:hover{text-decoration:underline}hr{text-align:center;border:0;margin:2rem 0}hr:before{content:'/////'}hr:after{content:attr(data-content) "/////"}pre{padding:1em;overflow-x:auto}table{width:100%}table,th,td{border-collapse:collapse;padding:0.4rem}code{text-size-adjust:100%;-ms-text-size-adjust:100%;-moz-text-size-adjust:100%;-webkit-text-size-adjust:100%}code:not(pre>code){padding:0.1em 0.2em;font-size:90%}code.has-jax{-webkit-font-smoothing:antialiased;background:inherit !important;border:none !important;font-size:100%}blockquote{padding:1rem}blockquote p{margin:0}img{max-width:100%;display:block;margin:0 auto}figcaption{text-align:center;opacity:0.5}details{padding:1rem}details summary{text-decoration:none}details[open] summary{margin-bottom:0.5em;padding-bottom:0.5em}.post-meta{display:flex;justify-content:space-between;align-items:center}.w{max-width:640px;margin:0 auto;padding:4rem 2rem}.toc{padding:1rem} diff --git a/resources/_gen/assets/css/main.scss_3d8be35fd0793eabe59c88efeab77a53.json b/resources/_gen/assets/css/main.scss_3d8be35fd0793eabe59c88efeab77a53.json new file mode 100644 index 0000000..08c00bb --- /dev/null +++ b/resources/_gen/assets/css/main.scss_3d8be35fd0793eabe59c88efeab77a53.json @@ -0,0 +1 @@ +{"Target":"/css/main.51652302d3a998bf7887aed5c2cf89141bbebdf45a2c8f87b0717a3cf4f51c4e53c694c328fb1de78c3a625a1c01f80745bf1f2f42c040647a245cbbb6c2d1d7.css","MediaType":"text/css","Data":{"Integrity":"sha512-UWUjAtOpmL94h67Vws+JFBu+vfRaLI+HsHF6PPT1HE5TxpTDKPsd54w6YlocAfgHRb8fL0LAQGR6JFy7tsLR1w=="}} \ No newline at end of file diff --git a/themes/dead-simple b/themes/dead-simple new file mode 160000 index 0000000..2386d86 --- /dev/null +++ b/themes/dead-simple @@ -0,0 +1 @@ +Subproject commit 2386d86b76ef53ee90c583602b52445b3c472e98 diff --git a/themes/default/archetypes/default.md b/themes/default/archetypes/default.md new file mode 100644 index 0000000..25b6752 --- /dev/null +++ b/themes/default/archetypes/default.md @@ -0,0 +1,5 @@ ++++ +date = '{{ .Date }}' +draft = true +title = '{{ replace .File.ContentBaseName "-" " " | title }}' ++++ diff --git a/themes/default/assets/css/components/footer.css b/themes/default/assets/css/components/footer.css new file mode 100644 index 0000000..abe2b5a --- /dev/null +++ b/themes/default/assets/css/components/footer.css @@ -0,0 +1,4 @@ +footer { + border-top: 1px solid #222; + margin-top: 1rem; +} diff --git a/themes/default/assets/css/components/header.css b/themes/default/assets/css/components/header.css new file mode 100644 index 0000000..8efea1e --- /dev/null +++ b/themes/default/assets/css/components/header.css @@ -0,0 +1,4 @@ +header { + border-bottom: 1px solid #222; + margin-bottom: 1rem; +} diff --git a/themes/default/assets/css/main.css b/themes/default/assets/css/main.css new file mode 100644 index 0000000..2ccbb6f --- /dev/null +++ b/themes/default/assets/css/main.css @@ -0,0 +1,34 @@ +/* https://bettermotherfuckingwebsite.com /*/ + +body { + margin: 40px auto; + max-width: 650px; + line-height: 1.6; + font-size: 18px; + color: #444; + padding: 0 10px; +} + +h1, h2, h3 { + line-height: 1.2; +} +/* +* { + background-color: #000022; + color: #00d56d; + font-family: monospace; + font-size: unset; +} +tr.alt_color:nth-child(even) {background-color: unset;} +blockquote {background: #000033;} +table, th, td {border: 1px solid #39c5bb;} +@media screen and (max-width: 600px) {table.tidy tr td{border-bottom: 2px dotted #002255;}} + +a:link {color:#00d56d;} +a:visited {color:#00d56d;} +a:hover {color: red!important; background-color:white!important;} +a.nohov:hover{background:none!important;color:white!important;} +hr, hr.dim {border-top: 1px solid #666666;} +.noprebg pre, code{background: none} +*.dimmed {color: #666666 !important;} +*/ diff --git a/themes/default/assets/js/main.js b/themes/default/assets/js/main.js new file mode 100644 index 0000000..e2aac52 --- /dev/null +++ b/themes/default/assets/js/main.js @@ -0,0 +1 @@ +console.log('This site was generated by Hugo.'); diff --git a/themes/default/content/_index.md b/themes/default/content/_index.md new file mode 100644 index 0000000..652623b --- /dev/null +++ b/themes/default/content/_index.md @@ -0,0 +1,9 @@ ++++ +title = 'Home' +date = 2023-01-01T08:00:00-07:00 +draft = false ++++ + +Laborum voluptate pariatur ex culpa magna nostrud est incididunt fugiat +pariatur do dolor ipsum enim. Consequat tempor do dolor eu. Non id id anim anim +excepteur excepteur pariatur nostrud qui irure ullamco. diff --git a/themes/default/content/posts/_index.md b/themes/default/content/posts/_index.md new file mode 100644 index 0000000..e7066c0 --- /dev/null +++ b/themes/default/content/posts/_index.md @@ -0,0 +1,7 @@ ++++ +title = 'Posts' +date = 2023-01-01T08:30:00-07:00 +draft = false ++++ + +Tempor est exercitation ad qui pariatur quis adipisicing aliquip nisi ea consequat ipsum occaecat. Nostrud consequat ullamco laboris fugiat esse esse adipisicing velit laborum ipsum incididunt ut enim. Dolor pariatur nulla quis fugiat dolore excepteur. Aliquip ad quis aliqua enim do consequat. diff --git a/themes/default/content/posts/post-1.md b/themes/default/content/posts/post-1.md new file mode 100644 index 0000000..3e3fc6b --- /dev/null +++ b/themes/default/content/posts/post-1.md @@ -0,0 +1,10 @@ ++++ +title = 'Post 1' +date = 2023-01-15T09:00:00-07:00 +draft = false +tags = ['red'] ++++ + +Tempor proident minim aliquip reprehenderit dolor et ad anim Lorem duis sint eiusmod. Labore ut ea duis dolor. Incididunt consectetur proident qui occaecat incididunt do nisi Lorem. Tempor do laborum elit laboris excepteur eiusmod do. Eiusmod nisi excepteur ut amet pariatur adipisicing Lorem. + +Occaecat nulla excepteur dolore excepteur duis eiusmod ullamco officia anim in voluptate ea occaecat officia. Cillum sint esse velit ea officia minim fugiat. Elit ea esse id aliquip pariatur cupidatat id duis minim incididunt ea ea. Anim ut duis sunt nisi. Culpa cillum sit voluptate voluptate eiusmod dolor. Enim nisi Lorem ipsum irure est excepteur voluptate eu in enim nisi. Nostrud ipsum Lorem anim sint labore consequat do. diff --git a/themes/default/content/posts/post-2.md b/themes/default/content/posts/post-2.md new file mode 100644 index 0000000..22b8287 --- /dev/null +++ b/themes/default/content/posts/post-2.md @@ -0,0 +1,10 @@ ++++ +title = 'Post 2' +date = 2023-02-15T10:00:00-07:00 +draft = false +tags = ['red','green'] ++++ + +Anim eiusmod irure incididunt sint cupidatat. Incididunt irure irure irure nisi ipsum do ut quis fugiat consectetur proident cupidatat incididunt cillum. Dolore voluptate occaecat qui mollit laborum ullamco et. Ipsum laboris officia anim laboris culpa eiusmod ex magna ex cupidatat anim ipsum aute. Mollit aliquip occaecat qui sunt velit ut cupidatat reprehenderit enim sunt laborum. Velit veniam in officia nulla adipisicing ut duis officia. + +Exercitation voluptate irure in irure tempor mollit Lorem nostrud ad officia. Velit id fugiat occaecat do tempor. Sit officia Lorem aliquip eu deserunt consectetur. Aute proident deserunt in nulla aliquip dolore ipsum Lorem ut cupidatat consectetur sit sint laborum. Esse cupidatat sit sint sunt tempor exercitation deserunt. Labore dolor duis laborum est do nisi ut veniam dolor et nostrud nostrud. diff --git a/themes/default/content/posts/post-3/bryce-canyon.jpg b/themes/default/content/posts/post-3/bryce-canyon.jpg new file mode 100644 index 0000000000000000000000000000000000000000..9a923bea0d182c65213ad3a105fa05f61c881976 GIT binary patch literal 19224 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 {{ now.Year }}. All rights reserved.

diff --git a/themes/default/layouts/_partials/head.html b/themes/default/layouts/_partials/head.html new file mode 100644 index 0000000..02c2240 --- /dev/null +++ b/themes/default/layouts/_partials/head.html @@ -0,0 +1,5 @@ + + +{{ if .IsHome }}{{ site.Title }}{{ else }}{{ printf "%s | %s" .Title site.Title }}{{ end }} +{{ partialCached "head/css.html" . }} +{{ partialCached "head/js.html" . }} diff --git a/themes/default/layouts/_partials/head/css.html b/themes/default/layouts/_partials/head/css.html new file mode 100644 index 0000000..8897866 --- /dev/null +++ b/themes/default/layouts/_partials/head/css.html @@ -0,0 +1,15 @@ +{{- with resources.Get "css/main.css" }} + {{- $opts := dict + "minify" (cond hugo.IsDevelopment false true) + "sourceMap" (cond hugo.IsDevelopment "linked" "none") + }} + {{- with . | css.Build $opts }} + {{- if hugo.IsDevelopment }} + + {{- else }} + {{- with . | fingerprint }} + + {{- end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/themes/default/layouts/_partials/head/js.html b/themes/default/layouts/_partials/head/js.html new file mode 100644 index 0000000..0210efa --- /dev/null +++ b/themes/default/layouts/_partials/head/js.html @@ -0,0 +1,15 @@ +{{- with resources.Get "js/main.js" }} + {{- $opts := dict + "minify" (cond hugo.IsDevelopment false true) + "sourceMap" (cond hugo.IsDevelopment "linked" "none") + }} + {{- with . | js.Build $opts }} + {{- if hugo.IsDevelopment }} + + {{- else }} + {{- with . | fingerprint }} + + {{- end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/themes/default/layouts/_partials/header.html b/themes/default/layouts/_partials/header.html new file mode 100644 index 0000000..7980a00 --- /dev/null +++ b/themes/default/layouts/_partials/header.html @@ -0,0 +1,2 @@ +

{{ site.Title }}

+{{ partial "menu.html" (dict "menuID" "main" "page" .) }} diff --git a/themes/default/layouts/_partials/menu.html b/themes/default/layouts/_partials/menu.html new file mode 100644 index 0000000..14245b5 --- /dev/null +++ b/themes/default/layouts/_partials/menu.html @@ -0,0 +1,51 @@ +{{- /* +Renders a menu for the given menu ID. + +@context {page} page The current page. +@context {string} menuID The menu ID. + +@example: {{ partial "menu.html" (dict "menuID" "main" "page" .) }} +*/}} + +{{- $page := .page }} +{{- $menuID := .menuID }} + +{{- with index site.Menus $menuID }} + +{{- end }} + +{{- define "_partials/inline/menu/walk.html" }} + {{- $page := .page }} + {{- range .menuEntries }} + {{- $attrs := dict "href" .URL }} + {{- if $page.IsMenuCurrent .Menu . }} + {{- $attrs = merge $attrs (dict "class" "active" "aria-current" "page") }} + {{- else if $page.HasMenuCurrent .Menu .}} + {{- $attrs = merge $attrs (dict "class" "ancestor" "aria-current" "true") }} + {{- end }} + {{- $name := .Name }} + {{- with .Identifier }} + {{- with T . }} + {{- $name = . }} + {{- end }} + {{- end }} +
  • + {{ $name }} + {{- with .Children }} +
      + {{- partial "inline/menu/walk.html" (dict "page" $page "menuEntries" .) }} +
    + {{- end }} +
  • + {{- end }} +{{- end }} diff --git a/themes/default/layouts/_partials/terms.html b/themes/default/layouts/_partials/terms.html new file mode 100644 index 0000000..8a6ebec --- /dev/null +++ b/themes/default/layouts/_partials/terms.html @@ -0,0 +1,23 @@ +{{- /* +For a given taxonomy, renders a list of terms assigned to the page. + +@context {page} page The current page. +@context {string} taxonomy The taxonomy. + +@example: {{ partial "terms.html" (dict "taxonomy" "tags" "page" .) }} +*/}} + +{{- $page := .page }} +{{- $taxonomy := .taxonomy }} + +{{- with $page.GetTerms $taxonomy }} + {{- $label := (index . 0).Parent.LinkTitle }} +
    +
    {{ $label }}:
    + +
    +{{- end }} diff --git a/themes/default/layouts/baseof.html b/themes/default/layouts/baseof.html new file mode 100644 index 0000000..7d17aa5 --- /dev/null +++ b/themes/default/layouts/baseof.html @@ -0,0 +1,17 @@ + + + + {{ partial "head.html" . }} + + +
    + {{ partial "header.html" . }} +
    +
    + {{ block "main" . }}{{ end }} +
    +
    + {{ partial "footer.html" . }} +
    + + diff --git a/themes/default/layouts/home.html b/themes/default/layouts/home.html new file mode 100644 index 0000000..0c76425 --- /dev/null +++ b/themes/default/layouts/home.html @@ -0,0 +1,9 @@ +{{ define "main" }} + {{ .Content }} + {{ range site.RegularPages }} +
    +

    {{ .LinkTitle }}

    + {{ .Summary }} +
    + {{ end }} +{{ end }} diff --git a/themes/default/layouts/page.html b/themes/default/layouts/page.html new file mode 100644 index 0000000..7e286c8 --- /dev/null +++ b/themes/default/layouts/page.html @@ -0,0 +1,10 @@ +{{ define "main" }} +

    {{ .Title }}

    + + {{ $dateMachine := .Date | time.Format "2006-01-02T15:04:05-07:00" }} + {{ $dateHuman := .Date | time.Format ":date_long" }} + + + {{ .Content }} + {{ partial "terms.html" (dict "taxonomy" "tags" "page" .) }} +{{ end }} diff --git a/themes/default/layouts/section.html b/themes/default/layouts/section.html new file mode 100644 index 0000000..748f2f5 --- /dev/null +++ b/themes/default/layouts/section.html @@ -0,0 +1,10 @@ +{{ define "main" }} +

    {{ .Title }}

    + {{ .Content }} + {{ range .Pages }} +
    +

    {{ .LinkTitle }}

    + {{ .Summary }} +
    + {{ end }} +{{ end }} diff --git a/themes/default/layouts/taxonomy.html b/themes/default/layouts/taxonomy.html new file mode 100644 index 0000000..c2e7875 --- /dev/null +++ b/themes/default/layouts/taxonomy.html @@ -0,0 +1,7 @@ +{{ define "main" }} +

    {{ .Title }}

    + {{ .Content }} + {{ range .Pages }} +

    {{ .LinkTitle }}

    + {{ end }} +{{ end }} diff --git a/themes/default/layouts/term.html b/themes/default/layouts/term.html new file mode 100644 index 0000000..c2e7875 --- /dev/null +++ b/themes/default/layouts/term.html @@ -0,0 +1,7 @@ +{{ define "main" }} +

    {{ .Title }}

    + {{ .Content }} + {{ range .Pages }} +

    {{ .LinkTitle }}

    + {{ end }} +{{ end }} diff --git a/themes/default/static/favicon.ico b/themes/default/static/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..67f8b777851849527933b78b1f98bd564d8255d1 GIT binary patch literal 15406 zcmeI3%WEH16vro|f`O{FV5Nc>unpZA42Xe(zeP4Fn0Fu>#YKe(c41L;qszMJ-bXDi z>L1W57+rSdLS5OG#!V^IKxvbj6n@gC#QOREdT$vg^US^Tf(#t)%-r+%o^#KA&hHll zeL;V)Z(l$;7%c7yg4co|7#w``eB{|6_?CCW!=`>H2!44k2#&ym2ojIpQ{=j)r>9?; zot^z+et!PXxw*M}BHinq>XMXKboc`~d=&+uPNklCgSOc%pC zkdxhQd};55Lm1#0hSD%6>D`)|ni^JI((I(w8QJADo{YL>VsSr%Ckg*U$-2s8+X=sG z{FIYm*irl0d{!y{D{f@u4p-n@#^$z+5S`e?RJu8p?Lq>0x`@}vIu7kfT z8Od5bMN4D{&~ch_$NgBcM#n%A`@~N^|ABlif3x_ci!t%#JQ&cWarai1&Z6~TkWOa9 zw}_GQ!9UZ~o(wFidYcy6DoF0rq<yz2-5e zTyl`ty!pUE-U+vC*KNN6@vklal>5+`8rxs}uh#LW?(tW105Q;7(Wx&Lm6uJ~)`e`X z^RF;~r?T~jY{_Q$A_iJ-m%jcoHny$5gr&~)r;P=1C}sVP-puv4#i0EM{FfkKed1Em zy4%`}me{Us{}sjpj#~DgVGO#rYen+cu9FI~=yTd>3AzfcLA`SnbFXu|pT#pXGc&>2(2!(N+83v|%y-!B zH|JI#fb9Zw1NxWuxyA*n7Wlp875YYr(Gs{zKTE)l_AX1Q6wmo%>|9k+6aP<2dk>lant}U*_E8rG3D-5uK;;yPx-8W%=Kfda!;c%(fl0 ze&XHrrr^uM0oGf>Z1DFnHhqLl>1%^5TzTuk|3H|*ul4(0o-gE;Z3>^kyq|VB2&R>$ z;3|M)g|TQza{|6pwl*t(FLk^UW^(9F%1?ditXdD)PeI>TZP%AQuxqb<#h1RS^?+T! z8Ck2^t}lCF{~KLC_TZ^~%@^LN9`I|g*;@RHecST~{FkHc(w1kiUj^&=w&0Dy`6E8G zdj4Yla1TF#N4vKWh(zA3A5dm)G|O@NEjS_AkOu zAJA`duQdQy-kiND%)+h<+}gi?*&_V<{_uGJE+68oBmMcH-Rl|t`yCgB%e&5Zsqq=>yyS- z+H#S&ls3nqdmTC0`~O|AJhXPJKi1jW{{U!5hztM# literal 0 HcmV?d00001 diff --git a/themes/nsp b/themes/nsp new file mode 160000 index 0000000..cfbfe4e --- /dev/null +++ b/themes/nsp @@ -0,0 +1 @@ +Subproject commit cfbfe4e8ed13ba6256c9ea076690dba30dd8765b diff --git a/themes/rustic/archetypes/default.md b/themes/rustic/archetypes/default.md new file mode 100644 index 0000000..25b6752 --- /dev/null +++ b/themes/rustic/archetypes/default.md @@ -0,0 +1,5 @@ ++++ +date = '{{ .Date }}' +draft = true +title = '{{ replace .File.ContentBaseName "-" " " | title }}' ++++ diff --git a/themes/rustic/assets/css/components/footer.css b/themes/rustic/assets/css/components/footer.css new file mode 100644 index 0000000..abe2b5a --- /dev/null +++ b/themes/rustic/assets/css/components/footer.css @@ -0,0 +1,4 @@ +footer { + border-top: 1px solid #222; + margin-top: 1rem; +} diff --git a/themes/rustic/assets/css/components/header.css b/themes/rustic/assets/css/components/header.css new file mode 100644 index 0000000..8efea1e --- /dev/null +++ b/themes/rustic/assets/css/components/header.css @@ -0,0 +1,4 @@ +header { + border-bottom: 1px solid #222; + margin-bottom: 1rem; +} diff --git a/themes/rustic/assets/css/main.css b/themes/rustic/assets/css/main.css new file mode 100644 index 0000000..6c0b660 --- /dev/null +++ b/themes/rustic/assets/css/main.css @@ -0,0 +1,15 @@ +@import "components/header.css"; +@import "components/footer.css"; + +body { + color: #222; + font-family: sans-serif; + line-height: 1.5; + margin: 1rem; + max-width: 768px; +} + +a { + color: #00e; + text-decoration: none; +} diff --git a/themes/rustic/assets/js/main.js b/themes/rustic/assets/js/main.js new file mode 100644 index 0000000..e2aac52 --- /dev/null +++ b/themes/rustic/assets/js/main.js @@ -0,0 +1 @@ +console.log('This site was generated by Hugo.'); diff --git a/themes/rustic/content/_index.md b/themes/rustic/content/_index.md new file mode 100644 index 0000000..652623b --- /dev/null +++ b/themes/rustic/content/_index.md @@ -0,0 +1,9 @@ ++++ +title = 'Home' +date = 2023-01-01T08:00:00-07:00 +draft = false ++++ + +Laborum voluptate pariatur ex culpa magna nostrud est incididunt fugiat +pariatur do dolor ipsum enim. Consequat tempor do dolor eu. Non id id anim anim +excepteur excepteur pariatur nostrud qui irure ullamco. diff --git a/themes/rustic/content/posts/_index.md b/themes/rustic/content/posts/_index.md new file mode 100644 index 0000000..e7066c0 --- /dev/null +++ b/themes/rustic/content/posts/_index.md @@ -0,0 +1,7 @@ ++++ +title = 'Posts' +date = 2023-01-01T08:30:00-07:00 +draft = false ++++ + +Tempor est exercitation ad qui pariatur quis adipisicing aliquip nisi ea consequat ipsum occaecat. Nostrud consequat ullamco laboris fugiat esse esse adipisicing velit laborum ipsum incididunt ut enim. Dolor pariatur nulla quis fugiat dolore excepteur. Aliquip ad quis aliqua enim do consequat. diff --git a/themes/rustic/content/posts/post-1.md b/themes/rustic/content/posts/post-1.md new file mode 100644 index 0000000..3e3fc6b --- /dev/null +++ b/themes/rustic/content/posts/post-1.md @@ -0,0 +1,10 @@ ++++ +title = 'Post 1' +date = 2023-01-15T09:00:00-07:00 +draft = false +tags = ['red'] ++++ + +Tempor proident minim aliquip reprehenderit dolor et ad anim Lorem duis sint eiusmod. Labore ut ea duis dolor. Incididunt consectetur proident qui occaecat incididunt do nisi Lorem. Tempor do laborum elit laboris excepteur eiusmod do. Eiusmod nisi excepteur ut amet pariatur adipisicing Lorem. + +Occaecat nulla excepteur dolore excepteur duis eiusmod ullamco officia anim in voluptate ea occaecat officia. Cillum sint esse velit ea officia minim fugiat. Elit ea esse id aliquip pariatur cupidatat id duis minim incididunt ea ea. Anim ut duis sunt nisi. Culpa cillum sit voluptate voluptate eiusmod dolor. Enim nisi Lorem ipsum irure est excepteur voluptate eu in enim nisi. Nostrud ipsum Lorem anim sint labore consequat do. diff --git a/themes/rustic/content/posts/post-2.md b/themes/rustic/content/posts/post-2.md new file mode 100644 index 0000000..22b8287 --- /dev/null +++ b/themes/rustic/content/posts/post-2.md @@ -0,0 +1,10 @@ ++++ +title = 'Post 2' +date = 2023-02-15T10:00:00-07:00 +draft = false +tags = ['red','green'] ++++ + +Anim eiusmod irure incididunt sint cupidatat. Incididunt irure irure irure nisi ipsum do ut quis fugiat consectetur proident cupidatat incididunt cillum. Dolore voluptate occaecat qui mollit laborum ullamco et. Ipsum laboris officia anim laboris culpa eiusmod ex magna ex cupidatat anim ipsum aute. Mollit aliquip occaecat qui sunt velit ut cupidatat reprehenderit enim sunt laborum. Velit veniam in officia nulla adipisicing ut duis officia. + +Exercitation voluptate irure in irure tempor mollit Lorem nostrud ad officia. Velit id fugiat occaecat do tempor. Sit officia Lorem aliquip eu deserunt consectetur. Aute proident deserunt in nulla aliquip dolore ipsum Lorem ut cupidatat consectetur sit sint laborum. Esse cupidatat sit sint sunt tempor exercitation deserunt. Labore dolor duis laborum est do nisi ut veniam dolor et nostrud nostrud. diff --git a/themes/rustic/content/posts/post-3/bryce-canyon.jpg b/themes/rustic/content/posts/post-3/bryce-canyon.jpg new file mode 100644 index 0000000000000000000000000000000000000000..9a923bea0d182c65213ad3a105fa05f61c881976 GIT binary patch literal 19224 zcmb4qWl-K+)NRlQx8gilad&rjcP;KvT#HMKI}|DI?oM%ccXusboZI)#y))n6ZznmE zWS!YrvrjVFCwt{%`C}VEla-W_1Rx*)0OH>Qe5?Ut04y{N3=A~vzXk*g3xY>QfQN&F z|AdT!h>HCQ2M7BT78Wi684)f%DLxh!5e+dZIRzCp6)qtiBON6p86_3ve@-A^K_GZI zcnkyt3`#sKJj(yIeRKopaKJDGJro2w0ErF(g%0u24}kyign{^v?*BJv2uLUxSO5g~ z4;4WJAR(ZjAfaI(p`l=5A)$bOAOMXHgF(t70{cnD81u7JU_5IsnW$+rAFe+(cX(V_l1hZgzt zSq0OWRn;jl_hS`6`Un04&;cP}JskLB5C($xJ%;F26Gl8tTnzZ+3kc|YPeZ*9+~xI00}&38O#;fMEdXumB=tfEyoBwgz^DQ4o*;Y87F`24#>v zCd8WWF;vsbjFJ16Hz4mb4Km#fz+~zK+-HQrkbiSP-x?rRRD=mzeXXFH1BKxa5diBX zWvFjE%hOQ&bN`Ohfv=fX5MgTnceir&JxLn{qO*h$0m?_k1QT?Rsf`NpCILueK2JmS zzDz>}{lBf79oR0O4FE&j<$!>pMu3sv*$TpOYfcz}E9PGe{AGdjX15$@s^w`&i-1p* z0iT?5px3R0NloRUH#ZxAEK~2<9JJxSPUcVJHh>6e4ho7jkQ;s>i~uiC0u?UwkJ-q( zE}&fDgAaV6P6z&wPlLQD1E3z=2}MflVs5Nz_(p|ht!lWbo|SeZA$o*n=d}@VR=WPt zg<8&T#D@AlJ!8ag`mfkT6sM2!H3%RyQ1 zoPZFM8@hNZlcyFn6-??4;l9g(P0kU;%t5&sxyvz?H}h5|ZAZI3(yz;Ag7sJ_to5Ea0y5^2uSo<&33&K?+pPh`U!6oQEK&fOcsMATj^`Ec0(HIR{ph4l7_FnUp?& zM!=oy+}|6pQh%@B43g-+2mKKSiwI_?1Co+Mr*FrQWG(JrCjj=NrCVX-m)Hqx(6`^& zo!F49RcuizMle1l)()(Y-Ec++Y2lsSzzD9U(~12E z8c_-8O}0hGa5+5)3vBsIb5<55c}Iws^hurB<3(-)1b=Lssxsrbh@F~&>FxJ>I-y6c zUIp{r_C1oA(_T*UDBR_0hwY7V#99kyZ`{KZ~zy1Nu^UP;fKxBeg;^PD^PIrQ(I$F{JCrA^qs;gm={hXStd zb}ng^Q(f%ZsE=f?bz=XXE4J-|4`4p>#tI_Zl*#(@>-0~w#>U}ys}F#^+cKH^R5cQU zzce;CuUiBW1h8=;TAd*`W}6n=y*(g5kO+{x4ME4`5M; z6_XEOhUq0NWtfAA9w+mJg1W*rcI7Lbaho&0|a!*BE;F<%E ze%46_(~mpCP_eh;2Y(~u@G9$wnOVNdalY)xF19&L@mJxBL7k1bIa0@{cu5R=Cb+K7!C zcT}#~59N+Do$TOi<(c_uGz6 zO9E&4X5((TsWr`^~CCQI!Ji<78yYG4=4`EQrAE9n3$ zx7{+~pp8kdQ)XZ8!kT-jT0%CZO;~vOn}P4I<<-_;_Hf0-LVxlqzYSWCxD)hWjPrhJ z+VuTc26dLuN4#0G!aPg;B(!0wIPx_L2v&dhFPUslDme(;rfzth8kTAb{A zX8Qn!XPgPiexr=l{X2=a-_%Gv>Ngl^in+GtFO#>7K+;Tz9SI?>?0+(22XnIxB>aSG zWv`&d*Sq+P$;5F{VS749{Q*QP4wN(>6W(v33_3m+=1>)1v#H%M&8F}O#wq+R&09AT zDbX43-=-aJ6|!5fe^1z6%1KEd<>4<*CwG~V5BT&jL4XkMC-NrtM_x>E@^UMk9(Kni zo;+KA4x(q?^3cv_8V0*|_X9vaajxJ>53#VA{2YS!<*IdPvv4#b3f#tq-}U&*73X&g zI>+5?_8^H7{M0Q1y(w7U$kgW=1?fjRQ4AJ3(Wl20Qw;yWh7>K-$|0xLhnlj{GL?~V zjA+SJys6uiB2MF$RBJ}aKRgQ@qMO4jrTYM+tLB+@ohUlOueEp3{2$kEpIe0td3LMV zR6cv^FM%PYiW-(o&NQN5Pkvi9#UF%$2|K;^oxL4l=?pSEartc!f6HP0knyW+3#5-v z(`H3uMu9&YqO7xxf2L|{u8UYu`h{jGLRLq)+s6&KtXnkfxXU)reCo3q9!8VQ`E(Pe zoKNV*19lT^Ogy-y)UHJ+%!A8Lh+fsDx4mN%#32uka$796@P&|TWQ zPb@anta75$!me*_OpIucPqG{u5wun%{w>?2tJ41?~^|iZqNyJ!;b=h) zQmzEcpr)J)YRaeRdk02Eq_IhF7JOH$)3dr5C>I}PuFCnAgZkymAN35|Ah3{j-mQ{P ze)KF2m1)hs|5m4XW+J|d73G>Pud9#!*UO9KK~Yem!^}y7P0|fxNX?#ah*U*Edr`u} zo)3$lvHLBm@yNv~i%L7wUhEERei`l#k!GzcZoqgc9}Eu^A*$2XY9$Zj&xY?UX)hbH zm+EdU^Njn^BBT5V!BB%J3SY*AW;MaKGyHy}vlWYri--UPV(YLo`k?eMRPKpvlO|4i z4nccyduHB`-J2Rxepc@J^Pt!zydpi;lCf#q&`!*k`_B#wpzwVtK^K&;5tM zB+8=}x1poJ^Q;qt!Wu)~qnuVUqdg{UABozn{gkqglZ@&)L83m=JV&HdJ@b&D!*^72 zo6;88b+|k5bpVQ_ZSFziJ&z{H<8!L&5_wt(tu7M>=Lm_39BmL}g3P(zjjg~h{2@%W zBCA(|qLnWzQ%95aHOjTGk2gbi7r11BOS4tzYxVr~j=R*HgVJ~mNPj=$G7b*Vw%06^ zyquG`WIijGV$4}zxz30tzLI0GYfhJy^FTzMbo20FE&Q3 z2O1~xIK46BH6oH#JC(+!Z&&kFUSR}j;!jn(Nh9#^nZCzsI#a1K<3)PB8v#Rjd$85! zM13-H`3ReI3$Eb<1*(lb;Y}STtlg+3`}b2hWKfuEk(!eAk@?17J*rMMXY`j(oQK=p zN9vZ_zC-UrZ8a2IS+{uLlklN}6f0;+s=`;TT%zALiJOctIdW># z_hDhr0M2Y%R31ARfjKG>jkUWn9^bGqzN-bHg9Jc+ z*|LY)bG(MS#}{G>S2s8;cw|PR13@zGldvE%=&Y{Ij3J_UI`$W{MQ_;Pujal)c@)X# z^X47vjI;jAB$oGJ3@I$f9wNJNFSa|xLQhkv6zdNlnBV<8OaD_w<-t#uk?u=LsbZ}B zJ}8d;eZ}*Z*>8B3{4?SE2^3}+^mcnLNbUl>@h^+Slbsn|j54rO+rJnm;i+zmmvcH| z9=nx6xI>r+dxJrO>T7xRuVIs`I`O-km|k(OE4Ny;{DDy)fLk#V%Y*o>-1M7}9gRCJ?iZyNd(IYZblV<%|G(fG=B`f64wB62r8@=tdHzU3S+ z>JwbaD^gs&1D<6&WX1%%X`+{6K?Jl)Bw;GSX9N7Unmlju6T4l=Is;#AVaf}8*%fG5 zn69--#RXe&FESz0Hzer~Tm4dEcYVm4V&-*woa~|Vtq1`6J zByThVU+R(y!tao|^jbS@(?}l)I1F;YX&}dCaG(nHU}Tt#PF>e`jrN+b+0#{>pRIAS zUmQUEM`cHZZ@(J~snjEaqMJr7+Z%!o#awI>Cnr_K82_3Gze$0>&woGHcnK+%Y!~*} zW9quKq#rQYYkFxQxkwTQmyRF?iTrzMh^g;K=^72w7j$44_A&LfAeaThuRRE~ExKmx zFPJ&S!bZ%gUImF!{``&Kp84~^s|W_^C@M4SdyG<}>$f=BlA}2~A3KXhZhKX0ER!%4 zF|Tg4bu_-cT(Upfr78u5&E~$13m2JZj46lGg{ob>J%H(NYZ{Ij>p|Odkt?kg@&qlg zQOWk(DKa?Es$s2FPb!@+^6>T|=N(!JE-nQ+x^;>we*OwXNLTgg`NnaAiVRX#o{!8?IUn9|$Q73vr|9pU8lNtOpEIUs%B*8* zq4TXXgpP&8vWRW|d0tjE6)r->qHayU{p!8|-@2hOBm~3cLGzZtiOLDFH~3_+?ehVa zx{C}AU;T)fAst#XhS8Ou>4eW3kpbKmT3R39$U3voYH~my#TDM8wIWD_h(+SZ@gFzt zpKzO2V_@0<53WWzC;XZhg7Ot?t@hRyb0HFO)Ameo{4|o5pi*6dee~&h>+I$>M}M{J z&Nei^cnszZ0r_4IMFMv$pG>*k;*ImGnfBHo?mB z$<)u9#PIZk)~xMv)nr6DuET%Qb#u>GOx*C!&CS{}F#2kDjpQIE?(_?_Vwr@5!ar>84Tb!J8ucKVw-AueKss!-H>UxLz7o}9Jt1zVilUxH2 z$xCU~S7(U3w^RLv2YqAOW4TxiDQKS%$5MskI%&j~O=tCOBS^3AQwYdH^T^}k7{gIy z56#8P+z){DF_7K|0lLvbBM}#hOhAh)rXx#%A>)o##$!amsrt-4onwxSVfB=;LbjGv zYmDS`$$_vC^WU@CNEw9v73g>Rg@HVwC$k$v8KM&k)nW8LShZ$C$wk4Jw%JXg+=4FH zM;l-7&8KSeMjb>cYDz6yl<3?v? zz-3ytM#T&*j7lU?u`SQDBN89HE+65o+;6IL4RnkA@y;s(?JNO7kbA3!+>k|Z zCaaWA%E$u~F<@R#PkFl#u0qGi#rEA3}6Udd3!Tidh~|ONA~W zJfP@CwS|wgjlX?8*OT5p2xMagd<&f3hTnIhQDr@KofEbM zbr3Oxl7a)LuhZ{IBbd)`i&I?ux7(tZ!p<$RE9{c;AR6OZiGsN~6de`ARWdYVlVh4) z0YE&z3DfDW>V=0oz$THfo0{al`!EuL9{NVfhROm>0v&-+>5PgBG=0DSY?3={jlIaF zd~)K#&|VRWhsYx7F1hZgBr?Z?hc_jgIwCUzbJ@XQs2HQ+`@U%@ip?9dk> zMjC{yr`Blwy4cjL{o1PE1Xa3cML1Ml2+34g(ICJxlayu=CW)jIc9JH{J;bMegIbIU zNc8IVMO22$ag&P&-B@7FcV}An#et z=@&TB0}Z7uf8vO6qAs9gem_;=nkF4s=F-=OxG}g<&AC2N&ACB19bOV6A3{2A(IDYE zjz#wsKa{0M!3`e7W2q=XkIyn?!Hqap27W)~nPdz70NiU+Jm6M2W21^`?HXnp>7+Ng z8ST>%sefLEL1NasyezT1T)rR4U9XefozMJ^#@dL&CJQnk%v(u#TQOYkFp=}FoMXbPjLj!@Dy3StD<*eWc1rf z@Qae&szr*A+rmBoW-r^rUxg!}LnIWIK|ee7F@(q#1iS|&lYE2Lj^-c>FQl3tW=q#6 zccaXsd9#N<5hV=CKH$yjui~>?b(_}q*O5){I9Wv6fnl`VlO7l>v3J+HvW&^Uql`J6 ztIZD+E5~p7SJ(gIz)s6xHHg5jh}b<=K^M1MQrB_px+YZTMvVoLF_j61XavzNLzeg5y-7%TP*5r;gfx~)$`4SBMy zo8&!w!iG+N{+6dkW!wGmLKY0%uy-wO)c(WF_?y8bf^?cjVT^Rp{qkh%LT3!xb$^!U z;Kp&tK!17d3*6U=dVBm*t4LVBfF9bt_(|{EDJT7#h{4Mi-n;|$lN&Cr6u$P6j&Sjm zlSY!nEK|T9`~nCzPNjVDLv|WC8E&)vCQ#r$&IJRFeeP9IXx4(a;k^E*%}|^%HvoZq z$Vfpojv7Z91{o>OB{^EX2tKWd2qtzAAi_U7A~4Kuq|goeqNzj6#Q0X^h5j ze*nL&4PJsET}tKc|wtEZT2j%w8o&p z){s#Go$^J+{!4AnDm70Jw?@)Ewdop4yeyGC$+@ZotnGNotSgnvmE0)$LJ>q%f*`2C zZ$8hn%dXaUghYtPrnZY=qmZC$5}03Mz&RZBUTKA(xvMKZ#^MA~cJbP({<@5Zu}{&- zHBD=CbA+(LT!4tfMSLc}{h}E`tDm+Os4K|V&t@v0#r>P;#_YDEivpSfhx~TE8u-g| zSSdjvJ-K#{qf?W$c&n7H*^zcgUrX~#jy?nlvcOei+im~Nh609hf;7G_XSr&>T{N*| znHf_uBBDhldKuirn|{MTNuC#L*?oxewf0&9Q5u`428?kaa_R}nq6?amXdtAo3)3O9 z3yKBDX0m}Mw`F)pf~U2_ZY);6&P)&!;75MRO%KZ`q%pPi`+-pW4rVjHNqe=7t)6W= z+{0b9#Nz0Lr>_?XUbVE~o zQkOR_F7cK*T@bI|4{f~cpjv?ob~$-j%J|OJzb0V!h^;;S5YAA02v;Z^#I38$rH8x% z;kj*w9)HSqW^gq@zr0$d#IhTM6ut$K1)eEL)UM~vtW&V`;uE&t&2|ZU6GmeT5cv}^ zM}#`-{3Q2FPJmJ_a@eEClAPBSXH#)`QeUQ}zu?dIrJd^~Do^D)flZqfzeSS4!&tPr z8v|3ns;m0#nTSi{Nz~1NmD$yhSGZbBp*NfWruc&uy0N zP?nT#{bm?+5q9O!DZk)!f;=mfC$dMYB1WvV;bFrkq3e=%e5&^B zVeK_jSyoKw{SROZlXM1geULF}0Nb6D%jmA?v*k}Y9wKchtEpC=g2800S;>JBBWAX_ zC{+o<{T&i@^0EYVe6vK3ep&x;=6{oH1zml#l>@G(IURjDTQ}?x<^5O_Rv{B)p9fE9 ziZm@~(@qk6IG%NB!Qd!mOxhyT;kdouAX&&zNrZn{xgJ!eFET)C;RZK#GZ5G1k`5VM z(J;1_mK%mEk{}kkH6(u&TU)@Uu#>@O9<+I;hV+1;|06B8H;ESBei;wQL^{fyAWvoj!!#6Hd=P{SDYtPHAWZn?ONSu8mAt&6>KuXf zuOhG3f*VM_S0zBlo3}gk`6*Bb7kgc4{D~gqKY?wf1TIHnm1(w#lbi*3AfK;y8(K5FEu5=yu5qjSdB*&>Cp;cq7B!x|HZ3rB{6mXF zcd{kF%i-5#&2RAE3Kt1<>bQrIr2=MAPE-6^4Y6nzshErDZnBKY_wW#SQRdT^A`Fijk$LimjHvuZj@LSyKhI?_=b1B=)7Q4r! zGvgvQZkjXDnYtOC9`&wc`fB zI*sFu2U&(eFNc{LpXKOI@;w7c65x5n*09=Gt$ID{ENx$GtqxekF;iES#(k#@J2Y!| zIL%%-e`7@Ou&aQhij@1We9X|bIV_?5mv!~AI9C&fESRvy3POS#z?Oo^m2fSyUnauMmWOp@Ai`KC%qGy;AV0g%#xe&# zdxBzCE@Utei`f(DRiz=;d4s1B%u<*iHP1A}Jh1bT;D6;3nW?gzdsY3EoEhUOm?C4V zd_jjz(Fxyp#kSx%Dss6ntQx*)G;Z=ETBuSn{{R>~cakn*WTZ8yra#>YMU3oAx9r+Y z4{gui?k1|Xuhvm(Xrq~JJKb`9sj2ev;+o~%+x4p%`vS5ivU8SWShipLVX4*vH67h@ zqWuA=&vae)wu7=?g-qQiEK4Q!rS;IqTS#2G2VG+5%nz9QKs#O2bpA-cxKupmNn|ee zp3qVz521~=T|a=!q}QaSdCv~6=B>QHBQuP#znqGrrzkx*&l58*CcT~JrWd~mid8?c zq$r;ufuTY*a3NDJ9*B{&B>krJ+EU(6;@&f2<4X2n)FKq+TXugKHu_VRf5pUMsi+5| z4R~O9qX?#zY{c$Hct}KH-{>t52Af64jp{gS)Cqz8ZIaW2wC8^%uCL&kGR7Q=s?-?li8v@CLLJB(V^x-qxoa*9;@j& zesX-yDmLZkLdB35F(wI@nv^nO2|VY{ow`fL{JyqA9cv{YI0zEwq?53$)u# zkRzUVnG&G3E2&+qWhG2=6kfZ>!nQ&dsN*aJt3j%y@lX6|l%~R^YINK7H*>K(BB19e zKgf`8yPE1J$WgKQZd%_!k1ibRx0j5Xc{`2pH#0$MqNM2ri;1JNDhs|L+`*6{>?G;a zAtw)r{5osl&}@Q=sq}pNIxqj>JWQ`ET0J>`wN{uc%&2AgV8l3puk=q=Yh~s`&&Xu0 z^?up0os65Sc_?X^QTgz#Xad_Z(f#3>WqF+ln&=3CE^ExQ%i}aPy=Yf8mSG)F#AAT5 z!}AUf3CxmoMsZQYQ5>Sy&EcyQQCPouMWQ(b%F2|6eWe7qI&JIj#EoVTl5x05qx;&D zH4!k)5)>84bQ$g{Ir(h4Rz5|a^Y@*_2WI=xUXGt7@C~HHe;@0Vx<%>oZs<4Wm#-Ae zhaX&rO1YnK6$>$@u6A=wj8yOBO$-)11~xkaEx-;^I?l65YMMa2(v!y42b{v=d@Mdf1OzM6D~~-0`6Q;Ryrx ztez*r@FNU&S7XnLAJuR{oK>m~@5y9c;9p`O>u!Ns_+|CU@nrEYBKXoklldnfLQp13 zg`d9b*0_c#7ODR0>LM9C$3hm(hs*1Drw)E2~K<*~^DMA@8@O3UhUr!5kD2RD6; z71a(9=@#iaq`gRtK1jqlgymtf2KCb+c?r^ClcKXNP0bkc9{`QTQ!G*1$wQUv{(H&B zAl>;2`(o-fucX#t{BLnhnAm04BNEHmD(ymixn(hW@{Cso4k08xU5R3c`6L^QLz;aG zC^1a2?2K%E^s|U_l^D#_`tbb}ixbDLH`)$UZu;6294#SON{pvEk{=_S03&cL05X26 zs54iXSB%0Z`-m zDFeA38f_+*qV$E5r35VYuPjo+V}(pK0&-t}EE+Tn3U~UVW7b-M+w`Qc9~6%o;xR_I zM+g+_I7ZLtw|-KKjT-0r&kz|jWboCdR?eP-aCb+I8juMH&7t|Rhh93kW*B^$3_9)t zCZyohWRGus)?^VJRvE&5#u*2!kPvUenQzDQB@F_23E~!M!VbZ45|)xt#2Qhh5!S!V z_7gxLp5aQTw6twT^WSUGOysd-k`;EKNeDcSQpl6V>XOYNOGt;L7J8X(l}jbSz0wq3dQyjsXo91#l*?pgnOp4^(=KS^ z%4fcC;#1?`^o5d=RmJLo14E$_OXAqAa4PYOG-3PV2S8XZKVq(>fV+jWCU)i2d(EyE zuEsYAw@3C+41F1-s$pdjYR--g8iVGO?w4fsoTP2Ei{7=VxI?ztnJEsZM;kQP>U1Jf zM`MLJDlOACd)fZJFX1*KRl(QO$>kLxsCrxgb@xz_E|XqtRUmD=icM}wZdMkRc!!C3 zAUULzh~5o}9#;^iZ)940p~E3sTj}V)^(2u5OYIS5b_7-rjdY@?p%wLT*p3qjWkrdd zP=`P=U82jfUIB=RW>B)(6-qBsPWIP1Y2LIU6yFP?EU}K|_zYvXJx^XZn^r44a4@7g zC)eMLsIohyM$BLB;nI^>##fvgh(Z$6^+>IHNayXL1M>rlQ{cxKr#BQ`bfnZT2sk)P zQ_>9^4@MJLrtHbg8az+%j3*VjzZT1$M0KHf5YYr|Zbte@#*@T2fiofsLPe`x{+yj@ z%eGrg|Be?EtYM-+(kKWqE4SxU&uRf3^J%fAo~(eK4Is8`ag+x!aM4OgzQuoAo^+8Y z3N-Z?Lkv3@Wv$29cDeDRL$wtBvF3F^)1(S<1WgIr4P&rIM;5)}gS7Wobe8&Zp-UMb z8TC(qvr3af7;o)OZjO3QY!@?i_tf&D**@5{Kem_rPphN+d_Q+4NzM6dI(zpUrwZyf zsJZ1CP+8ppa!cLn-+tZwcdh>M7!zV@?D!}&ZYn4c(Y+FzSv4UEqOa)N1AQc^@4)N5 z#>kY*V}<^NABT8bN^_+FdntP}2GF89osTs{1;QiryZ0yajlU|K2IHsXbCg6_7qQfZ zaR)*S-;-Fj7Se1%h0&tKYA5dOMCjSV|A>d5s0|-J)^a@enbpB*;0mu&GqL5m-ZYTM zUqrN8ab~!X+ztp{f8$+rwr-b=W*O3+bGNuFSv61|X$Z){-H_rLWEFT`ygm+xmcvOc zl`i}zMKr}F3-ErkmM#$lI3hzO>YAmTzmrk3y!PLhiOUXzRu(9nz_+;E4CgVs#|-gI zk!8)xP)u)caq6!yrR=c%T!+F2(Vfzz8xW$M*S1Dj2Igxp4jm|W%24LfH1{aV;Jg!l z04VqEM>-r}>y!eQE@V1ioaU`-!xSbImqUHBiHRdouvCh-VDOGFnQ)l&-HUHE6RYfz zOY4-X?LruJk1BuoLDEKDet#BGM^}qXLoJ&469SlIN>z$jMBh*E?0`3D5PAO|Iz+q!)htBVj!90-?jSpGGYhO8>kLj`&I z`6>fzzRII@3`s+{g(z4MAXe&xPZq}TvalxCegN6`hz#pLV6NfoquGn%GsD7%RdPtsqR47D@a~XO=y&h`7L2tA`OS=M(D-A_sJW8P{0`Jpp5UX|= zxh38y%lx-|LIoeSBr@!Zn|yFWg0;ITY1R(GI7S$Mf|B=jlfa*7l-A#Ej_#8tZ z$*k_`pX2Tr7f;9FC|aS6|J-wgcLt9(M-e>I1#FFjK8FO2XyQ4w@WKi>d%iEQYeYjH zMbRs=WClmgqEk9J_wAt0H2owY+*Fb7q4bYI0F1(Ec z{-TvAkqJA{ukz)d`djtm&Xnrdq17L^Mdk;9xe8p0Oc>~(Z_`Q4y^b;6B2H?W49A1f zaLBT&b&p1PU87auXI%f)j}CMKm*GijAYgr5ri>*gr8A@%Cl`4VcE9}4UZuDNOoN_C zjQsr@X&aXRE~I||h@S3~lJ#6THv;=5mo=rMW!nL$T|DpiC!U+^)-t~piOELYw^Lzn zd>!VL5;iA~J6MwuAolWJd|3?B-FgnVf6o{tDmgi$+mEi%hOxE|o*xC!4u4Km_|+kX zQr3Jc1?@h8s8f9$A3p5t8%ldP^i9P?s+z+r*kJt!1bNwK#uIXv&}d(mvtwF0bop%MFHHNcIa}n%d+Bk)0+v&(A_i(dDdZX+}AFz050S z-#C^r_C-s|@ka@Mzx(4Bo!r5{#|F!$pO>=@V3NG{s>S*xs|;SQU<{XhSC3%#ItqeJ zn?jO7TsBD>Ks0wX5y!Pgj|C+^RJqu&y6bL?*+?!Zv->F{Q`>igiDZb1ITkVq4kfi& z?=kunz8=2vURXF>H%YzS>bEs`RD>svID8pd?-8%ikQo8t3H%NV2{{aHtZ$ZEYj>7g zm%#Wr6DEd%LO}RCTXu#KiK}Tkoh#e8jNOIX!*wHe?iL00%Y>S23kB!a=Per_4jx=F zKFBhtk{uanm#2#3mCx54j3*kv}e4-V$Ob3b@T4AI~+p=Ec zCm5l=+$Hc(?Tv>E|H)d&ko=)tzzscEiXUY*n}f5r7o$Pk5B)3W;_RVNGOX zO5g|$AtK!;_D%Efk_HR@Hq$(Yu2CvD`M2za=u^t@#HVla{omqyeLYY9;#Hbd-dOUe z+Y<%m=^9x7#%-wSGEX?9;ETxIPRz7i<9^Y~PA*kwx%(Q%j7%w>#GLx6*|`z6D9`BwIq&9*Dgn~|yfSV7Ody_K()p7#7oNHKM-5u%?1(ee{s z`I=pNh6#DPt5xA8vh=HDCklr`D>!^L*R8`& zr3(Fx4eF>4Qb}>2N3~O@`S*o^RF<_!EHdU=`4kKrc(YMrl~4Mz5u)v;HbH&UOe&KK zCTmIV9J|MN3bOWcT5}{Zt8cDHqv2KR-*#F^0f9*gkD`N5ft5O6-14kfqb^|j>pG6} z-NvOc<1cwFIWYPQSDePE?=)=uzzYqw?rkx~0_l4^JE^C|&C^TRN<=D}ZM@eiMIk#9_Wd4k8QF}y z+nKvXPP?PQMPl&1br)|`U@e+CNlLm6rpX|z#)!pf#c=j`Gd7T&`Om~mvo{!bwc+<6 zI$I3yhp(h5dMgJ()O#(=;JSRM<@7rK=-R4j;H%&i9A-q86Bz8izlgSo{)Lv^=0vEuz0v>e2&Evxsm5T zrRpcxNECyA#mmgNbrqA(3GmF)blHAR$}8&PrkR--1(s#z{_GWHl*vV_6=<=pWPgWq z6yTO(N)W}j_X2n|RFHxW@yyc~E!SFjdSl@m6Zuabb{&<)PfY$Cvs8@ zBx2bmC?#ED{7hb|Q*hMfGe=Lno2h%K+j6t682e93Gli9k&!Tn9yu#*o86clid3OJ=Ii#IBi)Ex*-nFWG_r!xq}c7Oyb*^x zf6bmhEp~J?->96JRwBcPNnK&+3OiTRNJZ<@u|9ow1T96}&334JRW8agO#XQAc9tso zH#zgRVK11lhS)x|Lj+Hg?s}YqnLkZ%8i9OnH}r3#1D_8y{i_LnVFyY_bIr zE%kD~1o|rt3}ACg0&}V1(X1}-rb-ob*QxA#y01(s7?OT!g4;uxrevUpYQi>qqUO9l zrH;p7dNml$=m*;1#AlHYAbU4=FjBGm>(|TeR_tAUQ3CGn179{J4|NVKcP!`#)6JZ! z+m^s7-R{NFKR3wOpNKOl+VsjXiS!-NB*hZjx%s2>33(4YITtyq>jSCcTfONS8<9EJ z>2>wB+&!Ij#B-9VN;Y|@wjz$4nvk(a#R(b3hiPi^2V&rnivMMtj1y?Ff z@)pwM%#PUxR^Ll4i+a4Swd#9ZPmLpVA@qnY=np4PrLz5l#LL?u zI?0BKFRkGYWd^hkmrE-I5fmpU7bKF$L~!etQLwr=>i6M|pf_FgyKP6rL?DFrhK;Nx z(2%nfHlr0T0bm;b#Jghg<*IJvLI8Y)s!MHVvF9Kni5R;OLvu<;#%0_rg;A?Hcx2v9 ztfXthPC1bE)&ysq>Jwk9;>DnuZ`KrVY5$II&DFd(XXDM|D|#t#XAlPd79^Mz7OhR|3c;XX*2mITp-r z^nU#2C6-DyJeI|_Bi_*3(9jYiEuEmlb%}~uiK{szVdU*JZPDh*qa@gxwL3PD^6XpT z-uy}5Ucx$ECS@ZjL5!#%Gv-Z-BePI3zQXjr$(u9Pnq1|3YnxB$2T++rP5h$nDAcxJtubFN?hrFFT=@R7=ptRUAey!)L zbG+lcSP-=p$+S5uA!il!SM}>nzAEf)nf814lAwea7J;O9?>J#~43$4R`=b1x{4`|= zYq!Z+MTomeMVU)m*Hudb!Nj?!dfkfIbw-{iQz$4_$Tio0_OU87yvyPXi9FrmDf46x2Kk5?a495qBIo<7UV$T;ObVvyXVdKmurmWQ z2TF9d27T_&r99zNR~3d9W@X z3!NcKlGLvV!WC#KTm6-i+YIZyJD-w#F|5T+?=J!Xk_S3(V6d0Dugcj*}7$o;;p zp#)*8fEEZS21&s+v zSN5?lQpR4kuH^Bv`?3ycbtkQUcHSv;FBT2gyY&*Kct?r7bCPRvGZ#iRoaqkzA;aHh z&)T`)<^Mi?7i>Hh!kS%%Bd z7^_QHtu>>ayr@-POITW`atP0O_M@qQk(JjDZQY;`DUqXr;qz07Uj@_%)Dj_`#!C1f;+?~M z7kl$-kLQq-ccSLFK2ux9d22PV@u}$=Lim#e?Va}(9`p& zFxm*l-Jo!X3SIJRQ!Fk&IdB_i63?a2Zs1N+b~BQ;Fx-A;r3>C|Vggm&43V6-P;Se7`{&5p41d)nxKe`u+FEgNFE-~Lfq zQ4_MM$VS40`|Oe}d-sYv!ubX!vdfq85dcXmktqcsN^2vTrLl$H|0TbF*-yVG>n-qd zcE1RVBSmJKpbv4>dqEY^64!~C?a)EWVw-oxqmS}XO->`T#3L{vXfq?q%0E%7t4;Tj zH;|{a(q&4eFoPo5k9}VF5!~;6UlndA$L!Ng-20us_9XE_+hPK2`^ME5y6?Xe*D%9j z;C_Ao1+9Hed>cAklHBd#%l;Ra3C9Yy@rPmej+*|)L2cPcTZ}b5a_puEXX7XbR`lui zzXES`_8bK*lC*lxPZnPXJ#>pQ3Wh30EU4;rk`3H(Ec9=?-}TKt{YekYOnydA*jw3w zFBZ&qV-D3CalFhe7)r_cJ0%P&;CBy?nDg`E{nM^o`3SVR>8G2TaLD~!?n!MVh@Sfa zJ#oaHYBtrS3kLEIxVn^R67n5P8WNY@QlV=OMozf9wXv^gRu45I9%lbW%5iWMhk<}| za8Ncgg_u!F-lVD!6D5P0D-ycdY<;D%;TVq*@3*-%tjo>yq|=~ncFKfmfsTY(lgw8a zH9<0`M?qV%M+VY3>{yuVd$4RH)fHx zk8ryMT=b~fM_tqjtzXqw;zDEC;+*bt5;p(tapmie$BegpCdae8JL%>~Y6sgyY#0uD z-IewZZsmLcNW|F}qVh8`SkdHrxKWXzL&UREDlh7dlAU=%|0iJzp7rxxN#tY@TQB;# zdZ(4vCcgyPy|||G~QG(w65eT zD9I(W(Lk*toSh;h(pJwv(L4olBCPtQ+ggSh@*~4I`ksLPYthBxI{O}GPcdCY*y&mh zk)@DqtRh)Q{%Z}+fB7DtYVL*@L!@xeH0Rqbq1+UfIdkdIR;d|S;yvkz$A5_aCw~uE zLmi`H_T>DBXl<$wCkNb*-nl%C-x}cS@$meP-$gt4-Ys{++Oi}DE2u2PKOmtbg(QAS z$7<)7k@8}au1<(}&mKkiWqcdqxpkYO(C3f7FuEmu?2pc5|+ao1ESUt z?71GZuWRX{*!ee7Ligs`R%aOzBj+2K_4VL#eJRd#sTT};a{4R0J#lGvr&G1Hy41A? zY@6HYibjLgN4FRQpQT|9d+nVQa_gj9UfxNwZ`l&Tyr z{{WNbBQ1=Md8c+s9F|f~V?E`oIeR%uki_||8Rbf-&jX?Q(rpbU&DM>lc!OJ$MbldD zOKH9yb}|Rq2?sbQ zj`U@MjBnXEq};2~S9g5S$!g32i6$8*ws_CmIj%divWr_=t9eBG#?u=goSbx~Em=*i zM2gn;P{BHRpEJ9Um6-M0Q#Hb9(hruITJXdp3-XZdgPMavt4p$Le-YkZw2>4rswxlV z8PDdna{6jwqV~30&P3A^W86D;tWAk+;YCndBeQh7JiDVp2M!1Q;1U=dCal zlb!_v8qTP!%s^EcC(@;{o)_btX?49~N8JlW9G+At$8wcIc|TG~ub=WV%2^vduNz3h zgFFG@Ypb0{<0lOjku0()LJX=w1$_WDw~K;Odp?87@*@?hJxuA=kQRGbJ{o3Frbqw{ zfG{(jxX*g^);Pzb$$2F%*#7{Dj^0_GW{N2OMe|E@Bc3_;=sjw#yC$qWsFpTUl>}oT z;E%mgCU?hob_t`lS2sxLjX_&3bftJ~ z^2RXOao_X$*2`u+a2VrD}2A+a=MCS5}eQ z01Ru%Wx*#o>C|JI%jJi&MUFwfFuB$>>$^zo?Uzo5%W#j&nO6aZ(m3o!IQHvGUP@|_ zalqFs4#&f-7-2lIOCeFX43MM#HP7-UZ1J*7y$;@VQ1>!|{T3BbkETv4cW4$gOJ`-L z>B;4Yx2qrg#xflJdVVTiNixU(|Xv8rIO-O%<;1pc?krUAOn$r zagTpm-jiLJT{F!!IPPSIXrj7zk9JdV{#^I3I?`vTqUy_d5W0{TcF;L<(~iF8r(;b~ zYdo_{qK!O&{HrYPZ(dB z)i8Ht=boSQ{MI`&ZBsQq0Jt-FzfXDRkukYYlls0>gg(Z){7E;JTRD8VC56&GuoGVT zJOU{iR&OpZlaZHUk&fVd@%z-UR6IC!VvMH;83!O5pgdpvQ}LF!p@Rj1)sJ z_2Zx;>}#SKrw;lD7|C*b4~9HtqU-lhV`X&G-9r+)vqj~snd`GBoF3KaW6K%za=6iD zs!wBS8i~vZq>_=edzss>%DqX?rCgd_jw(-}9a~tsw}v$^y_lHo0PSg2N9uMN+KRo& zB=i`iZH|)v07|EaOg5J@+SyrK&KyQ>FC!8(s9WbFJxS;ZILY)FqT(c&Wrv2Wbjz01 zZl#6v>ukwsW>7L)x&2NF>P`Xw0NhEbbh%)gd?KE6DqY-OPT+T*@ss zHg-8JR8W?aJ?+y#uBjT}$tw|r9=}>v1!b|Sf*@Copyright {{ now.Year }}. All rights reserved.

    diff --git a/themes/rustic/layouts/_partials/head.html b/themes/rustic/layouts/_partials/head.html new file mode 100644 index 0000000..02c2240 --- /dev/null +++ b/themes/rustic/layouts/_partials/head.html @@ -0,0 +1,5 @@ + + +{{ if .IsHome }}{{ site.Title }}{{ else }}{{ printf "%s | %s" .Title site.Title }}{{ end }} +{{ partialCached "head/css.html" . }} +{{ partialCached "head/js.html" . }} diff --git a/themes/rustic/layouts/_partials/head/css.html b/themes/rustic/layouts/_partials/head/css.html new file mode 100644 index 0000000..8897866 --- /dev/null +++ b/themes/rustic/layouts/_partials/head/css.html @@ -0,0 +1,15 @@ +{{- with resources.Get "css/main.css" }} + {{- $opts := dict + "minify" (cond hugo.IsDevelopment false true) + "sourceMap" (cond hugo.IsDevelopment "linked" "none") + }} + {{- with . | css.Build $opts }} + {{- if hugo.IsDevelopment }} + + {{- else }} + {{- with . | fingerprint }} + + {{- end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/themes/rustic/layouts/_partials/head/js.html b/themes/rustic/layouts/_partials/head/js.html new file mode 100644 index 0000000..0210efa --- /dev/null +++ b/themes/rustic/layouts/_partials/head/js.html @@ -0,0 +1,15 @@ +{{- with resources.Get "js/main.js" }} + {{- $opts := dict + "minify" (cond hugo.IsDevelopment false true) + "sourceMap" (cond hugo.IsDevelopment "linked" "none") + }} + {{- with . | js.Build $opts }} + {{- if hugo.IsDevelopment }} + + {{- else }} + {{- with . | fingerprint }} + + {{- end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/themes/rustic/layouts/_partials/header.html b/themes/rustic/layouts/_partials/header.html new file mode 100644 index 0000000..7980a00 --- /dev/null +++ b/themes/rustic/layouts/_partials/header.html @@ -0,0 +1,2 @@ +

    {{ site.Title }}

    +{{ partial "menu.html" (dict "menuID" "main" "page" .) }} diff --git a/themes/rustic/layouts/_partials/menu.html b/themes/rustic/layouts/_partials/menu.html new file mode 100644 index 0000000..14245b5 --- /dev/null +++ b/themes/rustic/layouts/_partials/menu.html @@ -0,0 +1,51 @@ +{{- /* +Renders a menu for the given menu ID. + +@context {page} page The current page. +@context {string} menuID The menu ID. + +@example: {{ partial "menu.html" (dict "menuID" "main" "page" .) }} +*/}} + +{{- $page := .page }} +{{- $menuID := .menuID }} + +{{- with index site.Menus $menuID }} + +{{- end }} + +{{- define "_partials/inline/menu/walk.html" }} + {{- $page := .page }} + {{- range .menuEntries }} + {{- $attrs := dict "href" .URL }} + {{- if $page.IsMenuCurrent .Menu . }} + {{- $attrs = merge $attrs (dict "class" "active" "aria-current" "page") }} + {{- else if $page.HasMenuCurrent .Menu .}} + {{- $attrs = merge $attrs (dict "class" "ancestor" "aria-current" "true") }} + {{- end }} + {{- $name := .Name }} + {{- with .Identifier }} + {{- with T . }} + {{- $name = . }} + {{- end }} + {{- end }} +
  • + {{ $name }} + {{- with .Children }} +
      + {{- partial "inline/menu/walk.html" (dict "page" $page "menuEntries" .) }} +
    + {{- end }} +
  • + {{- end }} +{{- end }} diff --git a/themes/rustic/layouts/_partials/terms.html b/themes/rustic/layouts/_partials/terms.html new file mode 100644 index 0000000..8a6ebec --- /dev/null +++ b/themes/rustic/layouts/_partials/terms.html @@ -0,0 +1,23 @@ +{{- /* +For a given taxonomy, renders a list of terms assigned to the page. + +@context {page} page The current page. +@context {string} taxonomy The taxonomy. + +@example: {{ partial "terms.html" (dict "taxonomy" "tags" "page" .) }} +*/}} + +{{- $page := .page }} +{{- $taxonomy := .taxonomy }} + +{{- with $page.GetTerms $taxonomy }} + {{- $label := (index . 0).Parent.LinkTitle }} +
    +
    {{ $label }}:
    + +
    +{{- end }} diff --git a/themes/rustic/layouts/baseof.html b/themes/rustic/layouts/baseof.html new file mode 100644 index 0000000..7d17aa5 --- /dev/null +++ b/themes/rustic/layouts/baseof.html @@ -0,0 +1,17 @@ + + + + {{ partial "head.html" . }} + + +
    + {{ partial "header.html" . }} +
    +
    + {{ block "main" . }}{{ end }} +
    +
    + {{ partial "footer.html" . }} +
    + + diff --git a/themes/rustic/layouts/home.html b/themes/rustic/layouts/home.html new file mode 100644 index 0000000..0c76425 --- /dev/null +++ b/themes/rustic/layouts/home.html @@ -0,0 +1,9 @@ +{{ define "main" }} + {{ .Content }} + {{ range site.RegularPages }} +
    +

    {{ .LinkTitle }}

    + {{ .Summary }} +
    + {{ end }} +{{ end }} diff --git a/themes/rustic/layouts/page.html b/themes/rustic/layouts/page.html new file mode 100644 index 0000000..7e286c8 --- /dev/null +++ b/themes/rustic/layouts/page.html @@ -0,0 +1,10 @@ +{{ define "main" }} +

    {{ .Title }}

    + + {{ $dateMachine := .Date | time.Format "2006-01-02T15:04:05-07:00" }} + {{ $dateHuman := .Date | time.Format ":date_long" }} + + + {{ .Content }} + {{ partial "terms.html" (dict "taxonomy" "tags" "page" .) }} +{{ end }} diff --git a/themes/rustic/layouts/section.html b/themes/rustic/layouts/section.html new file mode 100644 index 0000000..748f2f5 --- /dev/null +++ b/themes/rustic/layouts/section.html @@ -0,0 +1,10 @@ +{{ define "main" }} +

    {{ .Title }}

    + {{ .Content }} + {{ range .Pages }} +
    +

    {{ .LinkTitle }}

    + {{ .Summary }} +
    + {{ end }} +{{ end }} diff --git a/themes/rustic/layouts/taxonomy.html b/themes/rustic/layouts/taxonomy.html new file mode 100644 index 0000000..c2e7875 --- /dev/null +++ b/themes/rustic/layouts/taxonomy.html @@ -0,0 +1,7 @@ +{{ define "main" }} +

    {{ .Title }}

    + {{ .Content }} + {{ range .Pages }} +

    {{ .LinkTitle }}

    + {{ end }} +{{ end }} diff --git a/themes/rustic/layouts/term.html b/themes/rustic/layouts/term.html new file mode 100644 index 0000000..c2e7875 --- /dev/null +++ b/themes/rustic/layouts/term.html @@ -0,0 +1,7 @@ +{{ define "main" }} +

    {{ .Title }}

    + {{ .Content }} + {{ range .Pages }} +

    {{ .LinkTitle }}

    + {{ end }} +{{ end }} diff --git a/themes/rustic/static/favicon.ico b/themes/rustic/static/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..67f8b777851849527933b78b1f98bd564d8255d1 GIT binary patch literal 15406 zcmeI3%WEH16vro|f`O{FV5Nc>unpZA42Xe(zeP4Fn0Fu>#YKe(c41L;qszMJ-bXDi z>L1W57+rSdLS5OG#!V^IKxvbj6n@gC#QOREdT$vg^US^Tf(#t)%-r+%o^#KA&hHll zeL;V)Z(l$;7%c7yg4co|7#w``eB{|6_?CCW!=`>H2!44k2#&ym2ojIpQ{=j)r>9?; zot^z+et!PXxw*M}BHinq>XMXKboc`~d=&+uPNklCgSOc%pC zkdxhQd};55Lm1#0hSD%6>D`)|ni^JI((I(w8QJADo{YL>VsSr%Ckg*U$-2s8+X=sG z{FIYm*irl0d{!y{D{f@u4p-n@#^$z+5S`e?RJu8p?Lq>0x`@}vIu7kfT z8Od5bMN4D{&~ch_$NgBcM#n%A`@~N^|ABlif3x_ci!t%#JQ&cWarai1&Z6~TkWOa9 zw}_GQ!9UZ~o(wFidYcy6DoF0rq<yz2-5e zTyl`ty!pUE-U+vC*KNN6@vklal>5+`8rxs}uh#LW?(tW105Q;7(Wx&Lm6uJ~)`e`X z^RF;~r?T~jY{_Q$A_iJ-m%jcoHny$5gr&~)r;P=1C}sVP-puv4#i0EM{FfkKed1Em zy4%`}me{Us{}sjpj#~DgVGO#rYen+cu9FI~=yTd>3AzfcLA`SnbFXu|pT#pXGc&>2(2!(N+83v|%y-!B zH|JI#fb9Zw1NxWuxyA*n7Wlp875YYr(Gs{zKTE)l_AX1Q6wmo%>|9k+6aP<2dk>lant}U*_E8rG3D-5uK;;yPx-8W%=Kfda!;c%(fl0 ze&XHrrr^uM0oGf>Z1DFnHhqLl>1%^5TzTuk|3H|*ul4(0o-gE;Z3>^kyq|VB2&R>$ z;3|M)g|TQza{|6pwl*t(FLk^UW^(9F%1?ditXdD)PeI>TZP%AQuxqb<#h1RS^?+T! z8Ck2^t}lCF{~KLC_TZ^~%@^LN9`I|g*;@RHecST~{FkHc(w1kiUj^&=w&0Dy`6E8G zdj4Yla1TF#N4vKWh(zA3A5dm)G|O@NEjS_AkOu zAJA`duQdQy-kiND%)+h<+}gi?*&_V<{_uGJE+68oBmMcH-Rl|t`yCgB%e&5Zsqq=>yyS- z+H#S&ls3nqdmTC0`~O|AJhXPJKi1jW{{U!5hztM# literal 0 HcmV?d00001 diff --git a/themes/trainsh b/themes/trainsh new file mode 160000 index 0000000..c5cd778 --- /dev/null +++ b/themes/trainsh @@ -0,0 +1 @@ +Subproject commit c5cd778dd0ba785bb0bc6b78aa1449d7e5103615 -- 2.47.3