<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://agora.nasqueron.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Dereckson</id>
	<title>Nasqueron Agora - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://agora.nasqueron.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Dereckson"/>
	<link rel="alternate" type="text/html" href="https://agora.nasqueron.org/Special:Contributions/Dereckson"/>
	<updated>2026-08-07T07:32:59Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.46.0-alpha</generator>
	<entry>
		<id>https://agora.nasqueron.org/index.php?title=User:Dereckson/Arcane_Grove/BlueDrake&amp;diff=2566</id>
		<title>User:Dereckson/Arcane Grove/BlueDrake</title>
		<link rel="alternate" type="text/html" href="https://agora.nasqueron.org/index.php?title=User:Dereckson/Arcane_Grove/BlueDrake&amp;diff=2566"/>
		<updated>2026-08-05T01:57:11Z</updated>

		<summary type="html">&lt;p&gt;Dereckson: /* Components */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;BlueDrake&#039;&#039;&#039; is the name of the hybrid productivity-gaming workstation.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
=== Components ===&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
|+ BlueDrake parts&lt;br /&gt;
|-&lt;br /&gt;
! Category !! Brand !! Model !! Links&lt;br /&gt;
|-&lt;br /&gt;
| Case || Lian Li || [https://lian-li.com/product/lancool-iii/ Lancool III] || [https://drive.google.com/file/d/1kd9ku_raF2uXWeLD7voGfT4ZZ10XOizy/view?usp=sharing 📖]&lt;br /&gt;
|-&lt;br /&gt;
| Motherboard || Asus || [https://rog.asus.com/motherboards/rog-strix/rog-strix-b650e-e-gaming-wifi-model/ ROG Strix B650E-E Gaming WiFi] || [https://rog.asus.com/motherboards/rog-strix/rog-strix-b650e-e-gaming-wifi-model/helpdesk_manual/ 📖] [https://rog.asus.com/motherboards/rog-strix/rog-strix-b650e-e-gaming-wifi-model/helpdesk_download/ 📥]&lt;br /&gt;
|-&lt;br /&gt;
| CPU || AMD || [https://www.amd.com/en/products/processors/desktops/ryzen/7000-series/amd-ryzen-9-7900x.html Ryzen 9 7900X] || [https://www.amd.com/en/support/downloads/drivers.html/processors/ryzen/ryzen-7000-series/amd-ryzen-9-7900x.html 📥]&lt;br /&gt;
|-&lt;br /&gt;
| CPU Cooler || Noctua || [https://noctua.at/en/nh-d15s NH-D15S] || [https://noctua.at/en/nh-d15s/manuals 📖]&lt;br /&gt;
|-&lt;br /&gt;
| GPU || Sapphire / AMD || PURE Radeon RX 7700 XT 12GB || [https://www.sapphiretech.com/en/consumer/pure-radeon-rx-7700-xt-12g-gddr6-frostpunk2 📖]&lt;br /&gt;
|-&lt;br /&gt;
| RAM || G.Skill || Trident Z Neo DDR5 96 GB (2×48 GB) || [https://www.gskill.com/product/165/374/1682577390/F5-5600J4040D48GX2-TZ5RK 📖]&lt;br /&gt;
|-&lt;br /&gt;
| Storage || Kingston || Fury Renegade 2 TB NVMe M.2 (×2) || [https://www.kingston.com/en/ssd/gaming/fury-renegade-nvme-pcie-ssd 📖]&lt;br /&gt;
|-&lt;br /&gt;
| PSU || Seasonic || Core GX-750 || [https://seasonic.com/core-gx#specification 📖]&lt;br /&gt;
|-&lt;br /&gt;
| Screen || Alienware || AW3425DWM || [https://dl.dell.com/content/manual56809116-alienware-34-gaming-monitor-aw3425dwm-quick-start-guide.pdf?language=en-us 📖]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
=== FreeBSD ===&lt;br /&gt;
Things to check for GPU:&lt;br /&gt;
* Ollama on FreeBSD -&amp;gt; https://www.reddit.com/r/freebsd/comments/1d3hmmz/comment/lqiulx9/ / https://github.com/ollama/ollama/pull/4172 (&amp;lt;code&amp;gt;pkg install go122 cmake vulkan-headers vulkan-loader&amp;lt;/code&amp;gt;)&lt;br /&gt;
* GPU passthrough with bhyve -&amp;gt; https://wiki.freebsd.org/bhyve/pci_passthru&lt;/div&gt;</summary>
		<author><name>Dereckson</name></author>
	</entry>
	<entry>
		<id>https://agora.nasqueron.org/index.php?title=User:Dereckson/Arcane_Grove/BlueDrake&amp;diff=2565</id>
		<title>User:Dereckson/Arcane Grove/BlueDrake</title>
		<link rel="alternate" type="text/html" href="https://agora.nasqueron.org/index.php?title=User:Dereckson/Arcane_Grove/BlueDrake&amp;diff=2565"/>
		<updated>2026-08-05T01:54:47Z</updated>

		<summary type="html">&lt;p&gt;Dereckson: /* Components */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;BlueDrake&#039;&#039;&#039; is the name of the hybrid productivity-gaming workstation.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
=== Components ===&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
|+ BlueDrake parts&lt;br /&gt;
|-&lt;br /&gt;
! Category !! Brand !! Model !! Links&lt;br /&gt;
|-&lt;br /&gt;
| Case || Lian Li || [https://lian-li.com/product/lancool-iii/ Lancool III] || [https://drive.google.com/file/d/1kd9ku_raF2uXWeLD7voGfT4ZZ10XOizy/view?usp=sharing 📖]&lt;br /&gt;
|-&lt;br /&gt;
| Motherboard || Asus || [https://rog.asus.com/motherboards/rog-strix/rog-strix-b650e-e-gaming-wifi-model/ ROG Strix B650E-E Gaming WiFi] || [https://rog.asus.com/motherboards/rog-strix/rog-strix-b650e-e-gaming-wifi-model/helpdesk_manual/ 📖] [https://rog.asus.com/motherboards/rog-strix/rog-strix-b650e-e-gaming-wifi-model/helpdesk_download/ 📥]&lt;br /&gt;
|-&lt;br /&gt;
| CPU || AMD || Ryzen 9 7900X || [https://www.amd.com/en/products/cpu/amd-ryzen-9-7900x 📖]&lt;br /&gt;
|-&lt;br /&gt;
| CPU Cooler || Noctua || [https://noctua.at/en/nh-d15s NH-D15S] || [https://noctua.at/en/nh-d15s/manuals 📖]&lt;br /&gt;
|-&lt;br /&gt;
| GPU || Sapphire / AMD || PURE Radeon RX 7700 XT 12GB || [https://www.sapphiretech.com/en/consumer/pure-radeon-rx-7700-xt-12g-gddr6-frostpunk2 📖]&lt;br /&gt;
|-&lt;br /&gt;
| RAM || G.Skill || Trident Z Neo DDR5 96 GB (2×48 GB) || [https://www.gskill.com/product/165/374/1682577390/F5-5600J4040D48GX2-TZ5RK 📖]&lt;br /&gt;
|-&lt;br /&gt;
| Storage || Kingston || Fury Renegade 2 TB NVMe M.2 (×2) || [https://www.kingston.com/en/ssd/gaming/fury-renegade-nvme-pcie-ssd 📖]&lt;br /&gt;
|-&lt;br /&gt;
| PSU || Seasonic || Core GX-750 || [https://seasonic.com/core-gx#specification 📖]&lt;br /&gt;
|-&lt;br /&gt;
| Screen || AOC || C27G1 || [https://aoc.com/be-fr/gaming/products/monitors/c27g1/downloads 📥]&lt;br /&gt;
|-&lt;br /&gt;
| Screen || Alienware || AW3425DWM || [https://dl.dell.com/content/manual56809116-alienware-34-gaming-monitor-aw3425dwm-quick-start-guide.pdf?language=en-us 📖]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
=== FreeBSD ===&lt;br /&gt;
Things to check for GPU:&lt;br /&gt;
* Ollama on FreeBSD -&amp;gt; https://www.reddit.com/r/freebsd/comments/1d3hmmz/comment/lqiulx9/ / https://github.com/ollama/ollama/pull/4172 (&amp;lt;code&amp;gt;pkg install go122 cmake vulkan-headers vulkan-loader&amp;lt;/code&amp;gt;)&lt;br /&gt;
* GPU passthrough with bhyve -&amp;gt; https://wiki.freebsd.org/bhyve/pci_passthru&lt;/div&gt;</summary>
		<author><name>Dereckson</name></author>
	</entry>
	<entry>
		<id>https://agora.nasqueron.org/index.php?title=User:Dereckson/Arcane_Grove/BlueDrake&amp;diff=2564</id>
		<title>User:Dereckson/Arcane Grove/BlueDrake</title>
		<link rel="alternate" type="text/html" href="https://agora.nasqueron.org/index.php?title=User:Dereckson/Arcane_Grove/BlueDrake&amp;diff=2564"/>
		<updated>2026-08-05T01:54:09Z</updated>

		<summary type="html">&lt;p&gt;Dereckson: /* Components */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;BlueDrake&#039;&#039;&#039; is the name of the hybrid productivity-gaming workstation.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
=== Components ===&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
|+ BlueDrake parts&lt;br /&gt;
|-&lt;br /&gt;
! Category !! Brand !! Model !! Links&lt;br /&gt;
|-&lt;br /&gt;
| Case || Lian Li || [https://lian-li.com/product/lancool-iii/ Lancool III] || [https://drive.google.com/file/d/1kd9ku_raF2uXWeLD7voGfT4ZZ10XOizy/view?usp=sharing 📖]&lt;br /&gt;
|-&lt;br /&gt;
| Motherboard || Asus || [https://rog.asus.com/motherboards/rog-strix/rog-strix-b650e-e-gaming-wifi-model/ ROG Strix B650E-E Gaming WiFi] || [https://rog.asus.com/motherboards/rog-strix/rog-strix-b650e-e-gaming-wifi-model/helpdesk_manual/ 📖] [https://rog.asus.com/motherboards/rog-strix/rog-strix-b650e-e-gaming-wifi-model/helpdesk_download/ 📥]&lt;br /&gt;
|-&lt;br /&gt;
| CPU || AMD || Ryzen 9 7900X || [https://www.amd.com/en/products/cpu/amd-ryzen-9-7900x 📖]&lt;br /&gt;
|-&lt;br /&gt;
| CPU Cooler || Noctua || NH-D15S || [https://noctua.at/en/nh-d15s 📝] [https://noctua.at/en/nh-d15s/manuals 📖]&lt;br /&gt;
|-&lt;br /&gt;
| GPU || Sapphire / AMD || PURE Radeon RX 7700 XT 12GB || [https://www.sapphiretech.com/en/consumer/pure-radeon-rx-7700-xt-12g-gddr6-frostpunk2 📖]&lt;br /&gt;
|-&lt;br /&gt;
| RAM || G.Skill || Trident Z Neo DDR5 96 GB (2×48 GB) || [https://www.gskill.com/product/165/374/1682577390/F5-5600J4040D48GX2-TZ5RK 📖]&lt;br /&gt;
|-&lt;br /&gt;
| Storage || Kingston || Fury Renegade 2 TB NVMe M.2 (×2) || [https://www.kingston.com/en/ssd/gaming/fury-renegade-nvme-pcie-ssd 📖]&lt;br /&gt;
|-&lt;br /&gt;
| PSU || Seasonic || Core GX-750 || [https://seasonic.com/core-gx#specification 📖]&lt;br /&gt;
|-&lt;br /&gt;
| Screen || AOC || C27G1 || [https://aoc.com/be-fr/gaming/products/monitors/c27g1/downloads 📥]&lt;br /&gt;
|-&lt;br /&gt;
| Screen || Alienware || AW3425DWM || [https://dl.dell.com/content/manual56809116-alienware-34-gaming-monitor-aw3425dwm-quick-start-guide.pdf?language=en-us 📖]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
=== FreeBSD ===&lt;br /&gt;
Things to check for GPU:&lt;br /&gt;
* Ollama on FreeBSD -&amp;gt; https://www.reddit.com/r/freebsd/comments/1d3hmmz/comment/lqiulx9/ / https://github.com/ollama/ollama/pull/4172 (&amp;lt;code&amp;gt;pkg install go122 cmake vulkan-headers vulkan-loader&amp;lt;/code&amp;gt;)&lt;br /&gt;
* GPU passthrough with bhyve -&amp;gt; https://wiki.freebsd.org/bhyve/pci_passthru&lt;/div&gt;</summary>
		<author><name>Dereckson</name></author>
	</entry>
	<entry>
		<id>https://agora.nasqueron.org/index.php?title=User:Dereckson/Arcane_Grove/BlueDrake&amp;diff=2563</id>
		<title>User:Dereckson/Arcane Grove/BlueDrake</title>
		<link rel="alternate" type="text/html" href="https://agora.nasqueron.org/index.php?title=User:Dereckson/Arcane_Grove/BlueDrake&amp;diff=2563"/>
		<updated>2026-08-05T01:53:04Z</updated>

		<summary type="html">&lt;p&gt;Dereckson: /* Components */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;BlueDrake&#039;&#039;&#039; is the name of the hybrid productivity-gaming workstation.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
=== Components ===&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
|+ BlueDrake parts&lt;br /&gt;
|-&lt;br /&gt;
! Category !! Brand !! Model !! Links&lt;br /&gt;
|-&lt;br /&gt;
| Case || Lian Li || [https://lian-li.com/product/lancool-iii/ Lancool III] || [https://drive.google.com/file/d/1kd9ku_raF2uXWeLD7voGfT4ZZ10XOizy/view?usp=sharing 📖]&lt;br /&gt;
|-&lt;br /&gt;
| Motherboard || Asus || [https://rog.asus.com/motherboards/rog-strix/rog-strix-b650e-e-gaming-wifi-model/ ROG Strix B650E-E Gaming WiFi] || [https://rog.asus.com/motherboards/rog-strix/rog-strix-b650e-e-gaming-wifi-model/helpdesk_manual/ 📖] [https://rog.asus.com/motherboards/rog-strix/rog-strix-b650e-e-gaming-wifi-model/helpdesk_download/ 📥]&lt;br /&gt;
|-&lt;br /&gt;
| CPU || AMD || Ryzen 9 7900X || [https://www.amd.com/en/products/cpu/amd-ryzen-9-7900x 📖]&lt;br /&gt;
|-&lt;br /&gt;
| CPU Cooler || Noctua || NH-D15S || [https://noctua.at/en/nh-d15s 📖] [https://noctua.at/en/nh-d15s/manuals&lt;br /&gt;
|-&lt;br /&gt;
| GPU || Sapphire / AMD || PURE Radeon RX 7700 XT 12GB || [https://www.sapphiretech.com/en/consumer/pure-radeon-rx-7700-xt-12g-gddr6-frostpunk2 📖]&lt;br /&gt;
|-&lt;br /&gt;
| RAM || G.Skill || Trident Z Neo DDR5 96 GB (2×48 GB) || [https://www.gskill.com/product/165/374/1682577390/F5-5600J4040D48GX2-TZ5RK 📖]&lt;br /&gt;
|-&lt;br /&gt;
| Storage || Kingston || Fury Renegade 2 TB NVMe M.2 (×2) || [https://www.kingston.com/en/ssd/gaming/fury-renegade-nvme-pcie-ssd 📖]&lt;br /&gt;
|-&lt;br /&gt;
| PSU || Seasonic || Core GX-750 || [https://seasonic.com/core-gx#specification 📖]&lt;br /&gt;
|-&lt;br /&gt;
| Screen || AOC || C27G1 || [https://aoc.com/be-fr/gaming/products/monitors/c27g1/downloads 📥]&lt;br /&gt;
|-&lt;br /&gt;
| Screen || Alienware || AW3425DWM || [https://dl.dell.com/content/manual56809116-alienware-34-gaming-monitor-aw3425dwm-quick-start-guide.pdf?language=en-us 📖]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
=== FreeBSD ===&lt;br /&gt;
Things to check for GPU:&lt;br /&gt;
* Ollama on FreeBSD -&amp;gt; https://www.reddit.com/r/freebsd/comments/1d3hmmz/comment/lqiulx9/ / https://github.com/ollama/ollama/pull/4172 (&amp;lt;code&amp;gt;pkg install go122 cmake vulkan-headers vulkan-loader&amp;lt;/code&amp;gt;)&lt;br /&gt;
* GPU passthrough with bhyve -&amp;gt; https://wiki.freebsd.org/bhyve/pci_passthru&lt;/div&gt;</summary>
		<author><name>Dereckson</name></author>
	</entry>
	<entry>
		<id>https://agora.nasqueron.org/index.php?title=Operations_grimoire/Deploy_with_Terraform&amp;diff=2562</id>
		<title>Operations grimoire/Deploy with Terraform</title>
		<link rel="alternate" type="text/html" href="https://agora.nasqueron.org/index.php?title=Operations_grimoire/Deploy_with_Terraform&amp;diff=2562"/>
		<updated>2026-07-23T13:19:56Z</updated>

		<summary type="html">&lt;p&gt;Dereckson: /* Troubleshoot */ Document tofu state rm&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Where to work? ==&lt;br /&gt;
We deploy from [[Complector]] using &amp;lt;code&amp;gt;/opt/salt/nasqueron-operations&amp;lt;/code&amp;gt; as our local copy of rOPS, authoritative for both Salt and Terraform&lt;br /&gt;
&lt;br /&gt;
You need to belong to the &amp;lt;code&amp;gt;ops&amp;lt;/code&amp;gt; group to be able to have access and have write-rights on the repository&lt;br /&gt;
&lt;br /&gt;
It&#039;s important to work from there to save a shared Terraform state.&lt;br /&gt;
&lt;br /&gt;
== Specific deployment notes ==&lt;br /&gt;
=== Vault / OpenBao ===&lt;br /&gt;
==== General notes ====&lt;br /&gt;
;OpenTofu support&lt;br /&gt;
As of 2026-02-07, the Vault provider isn&#039;t compiled for FreeBSD. You need to use Terraform instead.&lt;br /&gt;
&lt;br /&gt;
;Vault&lt;br /&gt;
You need a Vault token to allow the provider to connect.&lt;br /&gt;
&lt;br /&gt;
You also need to set VAULT_ADDR to https://172.27.27.7:8200 as Vault doesn&#039;t listen on 127.0.0.1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;shell&amp;quot;&amp;gt;&lt;br /&gt;
$ export VAULT_ADDR=https://172.27.27.7:8200&lt;br /&gt;
$ sudo /opt/salt/nasqueron-operations/utils/vault/issue-admin-token.py &amp;gt; ~/.vault-token&lt;br /&gt;
    &lt;br /&gt;
$ cd /opt/salt/nasqueron-operations/terraform/openbao&lt;br /&gt;
$ terraform init # if you&#039;ve a new entry requiring a module, it needs to be installed&lt;br /&gt;
$ terraform plan&lt;br /&gt;
$ terraform apply&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It could be interesting to maintain an alternative policy to admin for the Terraform provider, restricted to the current actions. Note benefits would be limited as those include policies management.&lt;br /&gt;
&lt;br /&gt;
==== Propagate secrets (DRP) ====&lt;br /&gt;
;No automatic secret rotation&lt;br /&gt;
Secrets rotation is disabled with a lifecycle management &amp;lt;code&amp;gt;ignore_changes = [ secret_id, ]&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
To rotate a secret, it needs first to be destroyed from terraform state:&lt;br /&gt;
&amp;lt;code&amp;gt;terraform destroy -target=module.viperserv_approle.vault_approle_auth_backend_role_secret_id.this&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;Full procedure &lt;br /&gt;
Once the AppRole have been created in Vault, they need to be provisioned to the relevant configuration files.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;shell&amp;quot;&amp;gt;&lt;br /&gt;
$ cd /opt/salt/nasqueron-operations/terraform/openbao&lt;br /&gt;
$ terraform init # if you&#039;ve a new entry requiring a module, it needs to be installed&lt;br /&gt;
$ terraform plan&lt;br /&gt;
$ terraform apply&lt;br /&gt;
&lt;br /&gt;
$ cd /opt/salt/nasqueron-operations&lt;br /&gt;
$ salt windriver state.sls_id /usr/local/etc/secrets/rhyne-wyse.yaml roles/reports/rhyne-wyse/config&lt;br /&gt;
$ salt windriver state.sls_id /srv/viperserv/.credentials roles/viperserv/eggdrop/config&lt;br /&gt;
# Missing for router&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;alert&amp;quot;&amp;gt;Important. Each time you&#039;ll reprovision the secrets, they will change.&lt;br /&gt;
&lt;br /&gt;
Don&#039;t forget to always apply this full procedure.&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== CARP OVH secrets usage ===&lt;br /&gt;
&lt;br /&gt;
The OVH credentials used by the CARP failover script are stored in Vault at:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;apps/network/carp-hyper-001-switch&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
These credentials are accessed by router-002 and router-003.  They are then used by a script triggered by devd to update the OVH failover IP MAC address depending on the CARP state (MASTER/BACKUP). The script authenticates to Vault using AppRole (via secretsmith) to retrieve them.&lt;br /&gt;
&lt;br /&gt;
The AppRole credentials (role_id and secret_id) used by the script are stored in:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ops/secrets/network/router/vault&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Vault secrets are provisioned using Terraform (openbao module), and must be propagated to the routers using Salt. &lt;br /&gt;
&lt;br /&gt;
The Vault Secrets may need to be rotated, so we need a simple way to propagate&lt;br /&gt;
updated credentials to routers. This is enabled by the mechanism&lt;br /&gt;
introduced in D4026.&lt;br /&gt;
&lt;br /&gt;
== Table of Terraform states ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Terraform and OpenBao states&lt;br /&gt;
|-&lt;br /&gt;
! Configuration !! State back-end !! Path !! Software to use&lt;br /&gt;
|-&lt;br /&gt;
| openbao || On disk || /opt/salt/nasqueron-operations/terraform/openbao/terraform.tfstate || Terraform&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
On disk paths are stored in Complector.&lt;br /&gt;
&lt;br /&gt;
== Troubleshoot ==&lt;br /&gt;
=== Error: Module not installed ===&lt;br /&gt;
&lt;br /&gt;
You need to run &amp;lt;code&amp;gt;tofu init&amp;lt;/code&amp;gt; to prepare for any new provider.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;shell&amp;quot;&amp;gt;&lt;br /&gt;
$ tofu plan&lt;br /&gt;
&lt;br /&gt;
│ Error: Module not installed&lt;br /&gt;
│ &lt;br /&gt;
│   on rhyne_wyse.tf line 23:&lt;br /&gt;
│   23: module &amp;quot;rhyne_wyse_approle&amp;quot; {&lt;br /&gt;
│ &lt;br /&gt;
│ This module is not yet installed. Run &amp;quot;tofu init&amp;quot; to install all modules required by this configuration.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Error: Incompatible provider version ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;shell&amp;quot;&amp;gt;&lt;br /&gt;
$ tofu init&lt;br /&gt;
&lt;br /&gt;
Initializing the backend...&lt;br /&gt;
Initializing modules...&lt;br /&gt;
- rhyne_wyse_approle in modules/app_credentials&lt;br /&gt;
&lt;br /&gt;
Initializing provider plugins...&lt;br /&gt;
- Finding hashicorp/vault versions matching &amp;quot;5.3.0&amp;quot;...&lt;br /&gt;
╷&lt;br /&gt;
│ Error: Incompatible provider version&lt;br /&gt;
│ &lt;br /&gt;
│ Provider registry.opentofu.org/hashicorp/vault v5.3.0 does not have a package available for your current platform, freebsd_amd64.&lt;br /&gt;
│ &lt;br /&gt;
│ Provider releases are separate from OpenTofu CLI releases, so not all providers are available for all platforms. Other versions of this provider may have different platforms supported.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On OpenTofu, some modules are only compiled for Linux, not for FreeBSD.&lt;br /&gt;
Switch to Terraform pending a solution to help the OpenTofu builds.&lt;br /&gt;
&lt;br /&gt;
=== State rollback ===&lt;br /&gt;
&lt;br /&gt;
When declaring new Terraform resources, it&#039;s possible to remove from the state an item, without actually destroying it at infrastructure level:&lt;br /&gt;
&lt;br /&gt;
    $ tofu state rm &amp;lt;state name&amp;gt;&lt;br /&gt;
    Removed ….…&lt;br /&gt;
    Successfully removed 1 resource instance(s).&lt;br /&gt;
&lt;br /&gt;
[[Category:Operations grimoire]]&lt;br /&gt;
[[Category:Terraform]]&lt;/div&gt;</summary>
		<author><name>Dereckson</name></author>
	</entry>
	<entry>
		<id>https://agora.nasqueron.org/index.php?title=Operations_grimoire/Operations_repository&amp;diff=2560</id>
		<title>Operations grimoire/Operations repository</title>
		<link rel="alternate" type="text/html" href="https://agora.nasqueron.org/index.php?title=Operations_grimoire/Operations_repository&amp;diff=2560"/>
		<updated>2026-07-18T20:43:06Z</updated>

		<summary type="html">&lt;p&gt;Dereckson: /* Python dependencies */ Works on Linux too&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Our configuration as code is stores in the operations (rOPS) repository.&lt;br /&gt;
&lt;br /&gt;
== Repository layout ==&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
|+ Content of rOPS&lt;br /&gt;
|-&lt;br /&gt;
! Path !! Description&lt;br /&gt;
|-&lt;br /&gt;
| _modules || Custom execution modules&lt;br /&gt;
|-&lt;br /&gt;
| _states || Custom states modules&lt;br /&gt;
|-&lt;br /&gt;
| _tests || Unit tests for custom modules, scripts, tests for repo&lt;br /&gt;
|-&lt;br /&gt;
| hotfixes || Fixes you need to run to solve a problem on the servers&lt;br /&gt;
|-&lt;br /&gt;
| pillar || Configuration data structures to use in the states&lt;br /&gt;
|-&lt;br /&gt;
| roles || The states to deploy, divided in roles and then in units&lt;br /&gt;
|-&lt;br /&gt;
| utils || Helper scripts to maintain the repository&lt;br /&gt;
|-&lt;br /&gt;
| terraform || OpenTofu / Terraform infrastructure configuration&lt;br /&gt;
|-&lt;br /&gt;
| map.jinja || As we deploy on several OS and distros, mapping of packages names or directories&lt;br /&gt;
|-&lt;br /&gt;
| top.sls || topfile: what we deploy where?&lt;br /&gt;
|-&lt;br /&gt;
| PORTS || Documentation of the ports used in the configuration&lt;br /&gt;
|-&lt;br /&gt;
| UIDs || Documentation of the users used in the configuration&lt;br /&gt;
|-&lt;br /&gt;
| GIDs || Documentation of the groups used in the configuration&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Contributions howto ==&lt;br /&gt;
=== Repository source ===&lt;br /&gt;
You&#039;ll find the Operations repository at https://devcentral.nasqueron.org/source/operations/&lt;br /&gt;
&lt;br /&gt;
If DevCentral isn&#039;t available, a mirror of the repository can be found at https://github.com/nasqueron/operations.&lt;br /&gt;
&lt;br /&gt;
=== Workflow of contributions ===&lt;br /&gt;
We follow the general workflow is described at [[How to contribute code]].&lt;br /&gt;
&lt;br /&gt;
Before committing a change to the main branch, you can test a deployment on a server.&lt;br /&gt;
In that case, merge in main immediately after the deployment as the repository is the source of truth for the server state.&lt;br /&gt;
&lt;br /&gt;
Log what you do on #nasqueron-ops, so it will be included at https://infra.nasqueron.org/servers-log/&lt;br /&gt;
&lt;br /&gt;
=== Code conventions ===&lt;br /&gt;
&#039;&#039;See also: [[Code conventions]].&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Python code: run `black` before committing&lt;br /&gt;
* YAML: indent with two spaces, including list bullets&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;yaml&amp;quot;&amp;gt;&lt;br /&gt;
id:&lt;br /&gt;
  method:&lt;br /&gt;
    - somekey: value&lt;br /&gt;
    - otherkey: value&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Environment setup ==&lt;br /&gt;
&lt;br /&gt;
Use of WindRiver is recommended if you wish to get an environment already installed for your contributions.&lt;br /&gt;
&lt;br /&gt;
=== Everywhere setup ===&lt;br /&gt;
This section cover topics needed both on our development servers or in your laptop.&lt;br /&gt;
&lt;br /&gt;
==== Python dependencies ====&lt;br /&gt;
&lt;br /&gt;
Create a virtual environment, then install dependencies from {{Ops file|requirements.txt}}:&lt;br /&gt;
&lt;br /&gt;
    mkdir -p $HOME/dev/python/ops&lt;br /&gt;
    python3 -m venv $HOME/dev/python/ops&lt;br /&gt;
    source $HOME/dev/python/ops/bin/activate&lt;br /&gt;
    pip install -r requirements.txt&lt;br /&gt;
&lt;br /&gt;
As of July 2026, it seems possible to also install Salt in the virtual environment and run tests:&lt;br /&gt;
&lt;br /&gt;
    pip install salt==3006.26&lt;br /&gt;
    make test&lt;br /&gt;
&lt;br /&gt;
(tested on WindRiver: with FreeBSD 15.1, Python 3.12.13, Salt 3006.26)&lt;br /&gt;
(tested on local workstation BlueDrake: with Fedora 42 Python 3.13.13, Salt 3006.26)&lt;br /&gt;
&lt;br /&gt;
==== Datacube ====&lt;br /&gt;
&lt;br /&gt;
If you&#039;re in the ops group, you&#039;ll need sometimes to deploy from branches. As our deployment server Complector doesn&#039;t have PHP installed (so no arc), you need to exchange branches through our datacube.&lt;br /&gt;
&lt;br /&gt;
On WindRiver:&lt;br /&gt;
&lt;br /&gt;
     git remote add datacube /datacube/git/operations.git&lt;br /&gt;
&lt;br /&gt;
Anywhere else:&lt;br /&gt;
&lt;br /&gt;
     git remote add datacube ssh://windriver.nasqueron.org/datacube/git/operations.git&lt;br /&gt;
&lt;br /&gt;
If you aren&#039;t in the ops groups, and have access to our devserver, you&#039;ll still be able to clone or pull from that directory, but not to write there (ie push branches).&lt;br /&gt;
&lt;br /&gt;
=== Local computer setup ===&lt;br /&gt;
&lt;br /&gt;
This section cover topics NOT needed on our development servers.&lt;br /&gt;
&lt;br /&gt;
==== macOS ====&lt;br /&gt;
&lt;br /&gt;
To run tests properly, install first:&lt;br /&gt;
&lt;br /&gt;
    brew install bats&lt;br /&gt;
    brew install python3.13&lt;br /&gt;
&lt;br /&gt;
You can now setup the virtual environment per everywhere setup instructions.&lt;br /&gt;
&lt;br /&gt;
Salt behaves correctly on macOS, so you can install it safely in the virtual environment:&lt;br /&gt;
&lt;br /&gt;
    pip install salt==3006.26&lt;br /&gt;
&lt;br /&gt;
Check the version on WindRiver or Complector with &amp;lt;code&amp;gt;salt --versions&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Finally, to run the tests, you need a recent version of make, but the BSD make currently shipped, as of Tahoe 26.5, isn&#039;t up-to-date:&lt;br /&gt;
&lt;br /&gt;
    brew install gmake&lt;br /&gt;
    (cd _tests &amp;amp;&amp;amp; gmake)&lt;br /&gt;
&lt;br /&gt;
==== Arcanist ====&lt;br /&gt;
&lt;br /&gt;
To use arc with the operations repository, our collection of patches is needed.&lt;br /&gt;
&lt;br /&gt;
If arcanist isn&#039;t installed through Git repository, best is to do like on devserver role:&lt;br /&gt;
&lt;br /&gt;
    mkdir /opt/phabricator &amp;amp;&amp;amp; cd /opt/phabricator&lt;br /&gt;
    git clone https://github.com/nasqueron/arcanist.git&lt;br /&gt;
    (cd arcanist &amp;amp;&amp;amp; git checkout production)&lt;br /&gt;
    ln -s /opt/phabricator/arcanist/bin/arc /usr/local/bin/&lt;br /&gt;
    git clone https://devcentral.nasqueron.org/source/shellcheck-linter.git&lt;br /&gt;
&lt;br /&gt;
If you&#039;ve already cloned Arcanist repository, switch to our branch production:&lt;br /&gt;
&lt;br /&gt;
    git remote add nasqueron git@github.com:nasqueron/arcanist.git&lt;br /&gt;
    git fetch --all&lt;br /&gt;
    git checkout production&lt;br /&gt;
&lt;br /&gt;
As of August 2024, there is no plan to make that repository available on DevCentral.&lt;br /&gt;
&lt;br /&gt;
You&#039;ll also need shellcheck library-linter library, normally at the same level than your arcanist repository.&lt;br /&gt;
&lt;br /&gt;
==== IDE configuration ====&lt;br /&gt;
[[File:PyCharm-TemplateLanguages.png|thumb|right|Screenshot of correctly configured template languages]]&lt;br /&gt;
The states .sls file are Jinja2 templates producing YAML files, or &amp;quot;jinja2+yaml&amp;quot;. If this case can&#039;t be handled by your IDE, it works best to use YAML syntax highlighting.&lt;br /&gt;
&lt;br /&gt;
If you use PyCharm or IntelliJ IDEA Ultimate, you can configure this scheme:&lt;br /&gt;
&lt;br /&gt;
* Allow YAML files to be Jinja2 templates&lt;br /&gt;
** Go to Settings &amp;gt; Languages &amp;amp; Frameworks &amp;gt; Template Languages&lt;br /&gt;
** Select Jinja2 as template language&lt;br /&gt;
** Add YAML in the list&lt;br /&gt;
* Open SLS as YAML&lt;br /&gt;
&lt;br /&gt;
== Linting ==&lt;br /&gt;
&lt;br /&gt;
=== pre-commit ===&lt;br /&gt;
You can use &#039;&#039;&#039;pre-commit&#039;&#039;&#039; you can install with &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; to get a hook running Python code to lint the repository before a commit.&lt;br /&gt;
&lt;br /&gt;
Beware if you use &amp;lt;code&amp;gt;arc diff&amp;lt;/code&amp;gt; without a commit first: your message will be lost if pre-commit raises an error, always use &amp;lt;code&amp;gt;git commit&amp;lt;/code&amp;gt; first.&lt;br /&gt;
&lt;br /&gt;
On FreeBSD, there is an issue to build with clang 16+ the ruamel yaml clib library. You can build the FreeBSD port devel/py-ruamel.yaml.clib and copy the .whl to a stable path, then install it in your virtual environment.&lt;br /&gt;
&lt;br /&gt;
On WindRiver, the .whl is available in /opt/python/py311, so you can:&lt;br /&gt;
&lt;br /&gt;
    $ python3 -m venv /path/to/your/virtualenv&lt;br /&gt;
    $ source /path/to/your/virtualenv/bin/activate&lt;br /&gt;
    $ pip install /opt/python/py311/ruamel.yaml.clib-0.2.8-cp311-cp311-freebsd_14_0_release_p3_amd64.whl&lt;br /&gt;
    $ pip install pre-commit&lt;br /&gt;
    $ make&lt;br /&gt;
    pre-commit install&lt;br /&gt;
    pre-commit installed at .git/hooks/pre-commit&lt;br /&gt;
    $ rehash&lt;br /&gt;
    $ pre-commit&lt;br /&gt;
&lt;br /&gt;
== Refactoring ==&lt;br /&gt;
&lt;br /&gt;
=== Rename a lot of files ===&lt;br /&gt;
&lt;br /&gt;
To move a directory and rename the &#039;&#039;Source file&#039;&#039; headers:&lt;br /&gt;
&lt;br /&gt;
    git mv roles/webserver-legacy/nginx/files roles/webserver-alkane/nginx/&lt;br /&gt;
    cd roles/webserver-alkane/nginx/&lt;br /&gt;
    find . -type f -name &#039;*.conf&#039; | xargs gsed -i s/webserver-legacy/webserver-alkane/g&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
* [[/FAQ]] - Frequently asked questions about the Operations repository&lt;br /&gt;
* [[How to contribute code]]&lt;br /&gt;
* [[Devserver reference]]&lt;/div&gt;</summary>
		<author><name>Dereckson</name></author>
	</entry>
	<entry>
		<id>https://agora.nasqueron.org/index.php?title=Operations_grimoire/Operations_repository&amp;diff=2559</id>
		<title>Operations grimoire/Operations repository</title>
		<link rel="alternate" type="text/html" href="https://agora.nasqueron.org/index.php?title=Operations_grimoire/Operations_repository&amp;diff=2559"/>
		<updated>2026-07-18T20:40:18Z</updated>

		<summary type="html">&lt;p&gt;Dereckson: /* Python dependencies */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Our configuration as code is stores in the operations (rOPS) repository.&lt;br /&gt;
&lt;br /&gt;
== Repository layout ==&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
|+ Content of rOPS&lt;br /&gt;
|-&lt;br /&gt;
! Path !! Description&lt;br /&gt;
|-&lt;br /&gt;
| _modules || Custom execution modules&lt;br /&gt;
|-&lt;br /&gt;
| _states || Custom states modules&lt;br /&gt;
|-&lt;br /&gt;
| _tests || Unit tests for custom modules, scripts, tests for repo&lt;br /&gt;
|-&lt;br /&gt;
| hotfixes || Fixes you need to run to solve a problem on the servers&lt;br /&gt;
|-&lt;br /&gt;
| pillar || Configuration data structures to use in the states&lt;br /&gt;
|-&lt;br /&gt;
| roles || The states to deploy, divided in roles and then in units&lt;br /&gt;
|-&lt;br /&gt;
| utils || Helper scripts to maintain the repository&lt;br /&gt;
|-&lt;br /&gt;
| terraform || OpenTofu / Terraform infrastructure configuration&lt;br /&gt;
|-&lt;br /&gt;
| map.jinja || As we deploy on several OS and distros, mapping of packages names or directories&lt;br /&gt;
|-&lt;br /&gt;
| top.sls || topfile: what we deploy where?&lt;br /&gt;
|-&lt;br /&gt;
| PORTS || Documentation of the ports used in the configuration&lt;br /&gt;
|-&lt;br /&gt;
| UIDs || Documentation of the users used in the configuration&lt;br /&gt;
|-&lt;br /&gt;
| GIDs || Documentation of the groups used in the configuration&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Contributions howto ==&lt;br /&gt;
=== Repository source ===&lt;br /&gt;
You&#039;ll find the Operations repository at https://devcentral.nasqueron.org/source/operations/&lt;br /&gt;
&lt;br /&gt;
If DevCentral isn&#039;t available, a mirror of the repository can be found at https://github.com/nasqueron/operations.&lt;br /&gt;
&lt;br /&gt;
=== Workflow of contributions ===&lt;br /&gt;
We follow the general workflow is described at [[How to contribute code]].&lt;br /&gt;
&lt;br /&gt;
Before committing a change to the main branch, you can test a deployment on a server.&lt;br /&gt;
In that case, merge in main immediately after the deployment as the repository is the source of truth for the server state.&lt;br /&gt;
&lt;br /&gt;
Log what you do on #nasqueron-ops, so it will be included at https://infra.nasqueron.org/servers-log/&lt;br /&gt;
&lt;br /&gt;
=== Code conventions ===&lt;br /&gt;
&#039;&#039;See also: [[Code conventions]].&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Python code: run `black` before committing&lt;br /&gt;
* YAML: indent with two spaces, including list bullets&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;yaml&amp;quot;&amp;gt;&lt;br /&gt;
id:&lt;br /&gt;
  method:&lt;br /&gt;
    - somekey: value&lt;br /&gt;
    - otherkey: value&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Environment setup ==&lt;br /&gt;
&lt;br /&gt;
Use of WindRiver is recommended if you wish to get an environment already installed for your contributions.&lt;br /&gt;
&lt;br /&gt;
=== Everywhere setup ===&lt;br /&gt;
This section cover topics needed both on our development servers or in your laptop.&lt;br /&gt;
&lt;br /&gt;
==== Python dependencies ====&lt;br /&gt;
&lt;br /&gt;
Create a virtual environment, then install dependencies from {{Ops file|requirements.txt}}:&lt;br /&gt;
&lt;br /&gt;
    mkdir -p $HOME/dev/python/ops&lt;br /&gt;
    python3 -m venv $HOME/dev/python/ops&lt;br /&gt;
    source $HOME/dev/python/ops/bin/activate&lt;br /&gt;
    pip install -r requirements.txt&lt;br /&gt;
&lt;br /&gt;
As of July 2026, it seems possible to also install Salt in the virtual environment and run tests:&lt;br /&gt;
&lt;br /&gt;
    pip install salt==3006.26&lt;br /&gt;
    make test&lt;br /&gt;
&lt;br /&gt;
(tested on WindRiver, so with FreeBSD 15.1, Python 3.12.13, Salt 3006.26)&lt;br /&gt;
&lt;br /&gt;
==== Datacube ====&lt;br /&gt;
&lt;br /&gt;
If you&#039;re in the ops group, you&#039;ll need sometimes to deploy from branches. As our deployment server Complector doesn&#039;t have PHP installed (so no arc), you need to exchange branches through our datacube.&lt;br /&gt;
&lt;br /&gt;
On WindRiver:&lt;br /&gt;
&lt;br /&gt;
     git remote add datacube /datacube/git/operations.git&lt;br /&gt;
&lt;br /&gt;
Anywhere else:&lt;br /&gt;
&lt;br /&gt;
     git remote add datacube ssh://windriver.nasqueron.org/datacube/git/operations.git&lt;br /&gt;
&lt;br /&gt;
If you aren&#039;t in the ops groups, and have access to our devserver, you&#039;ll still be able to clone or pull from that directory, but not to write there (ie push branches).&lt;br /&gt;
&lt;br /&gt;
=== Local computer setup ===&lt;br /&gt;
&lt;br /&gt;
This section cover topics NOT needed on our development servers.&lt;br /&gt;
&lt;br /&gt;
==== macOS ====&lt;br /&gt;
&lt;br /&gt;
To run tests properly, install first:&lt;br /&gt;
&lt;br /&gt;
    brew install bats&lt;br /&gt;
    brew install python3.13&lt;br /&gt;
&lt;br /&gt;
You can now setup the virtual environment per everywhere setup instructions.&lt;br /&gt;
&lt;br /&gt;
Salt behaves correctly on macOS, so you can install it safely in the virtual environment:&lt;br /&gt;
&lt;br /&gt;
    pip install salt==3006.26&lt;br /&gt;
&lt;br /&gt;
Check the version on WindRiver or Complector with &amp;lt;code&amp;gt;salt --versions&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Finally, to run the tests, you need a recent version of make, but the BSD make currently shipped, as of Tahoe 26.5, isn&#039;t up-to-date:&lt;br /&gt;
&lt;br /&gt;
    brew install gmake&lt;br /&gt;
    (cd _tests &amp;amp;&amp;amp; gmake)&lt;br /&gt;
&lt;br /&gt;
==== Arcanist ====&lt;br /&gt;
&lt;br /&gt;
To use arc with the operations repository, our collection of patches is needed.&lt;br /&gt;
&lt;br /&gt;
If arcanist isn&#039;t installed through Git repository, best is to do like on devserver role:&lt;br /&gt;
&lt;br /&gt;
    mkdir /opt/phabricator &amp;amp;&amp;amp; cd /opt/phabricator&lt;br /&gt;
    git clone https://github.com/nasqueron/arcanist.git&lt;br /&gt;
    (cd arcanist &amp;amp;&amp;amp; git checkout production)&lt;br /&gt;
    ln -s /opt/phabricator/arcanist/bin/arc /usr/local/bin/&lt;br /&gt;
    git clone https://devcentral.nasqueron.org/source/shellcheck-linter.git&lt;br /&gt;
&lt;br /&gt;
If you&#039;ve already cloned Arcanist repository, switch to our branch production:&lt;br /&gt;
&lt;br /&gt;
    git remote add nasqueron git@github.com:nasqueron/arcanist.git&lt;br /&gt;
    git fetch --all&lt;br /&gt;
    git checkout production&lt;br /&gt;
&lt;br /&gt;
As of August 2024, there is no plan to make that repository available on DevCentral.&lt;br /&gt;
&lt;br /&gt;
You&#039;ll also need shellcheck library-linter library, normally at the same level than your arcanist repository.&lt;br /&gt;
&lt;br /&gt;
==== IDE configuration ====&lt;br /&gt;
[[File:PyCharm-TemplateLanguages.png|thumb|right|Screenshot of correctly configured template languages]]&lt;br /&gt;
The states .sls file are Jinja2 templates producing YAML files, or &amp;quot;jinja2+yaml&amp;quot;. If this case can&#039;t be handled by your IDE, it works best to use YAML syntax highlighting.&lt;br /&gt;
&lt;br /&gt;
If you use PyCharm or IntelliJ IDEA Ultimate, you can configure this scheme:&lt;br /&gt;
&lt;br /&gt;
* Allow YAML files to be Jinja2 templates&lt;br /&gt;
** Go to Settings &amp;gt; Languages &amp;amp; Frameworks &amp;gt; Template Languages&lt;br /&gt;
** Select Jinja2 as template language&lt;br /&gt;
** Add YAML in the list&lt;br /&gt;
* Open SLS as YAML&lt;br /&gt;
&lt;br /&gt;
== Linting ==&lt;br /&gt;
&lt;br /&gt;
=== pre-commit ===&lt;br /&gt;
You can use &#039;&#039;&#039;pre-commit&#039;&#039;&#039; you can install with &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; to get a hook running Python code to lint the repository before a commit.&lt;br /&gt;
&lt;br /&gt;
Beware if you use &amp;lt;code&amp;gt;arc diff&amp;lt;/code&amp;gt; without a commit first: your message will be lost if pre-commit raises an error, always use &amp;lt;code&amp;gt;git commit&amp;lt;/code&amp;gt; first.&lt;br /&gt;
&lt;br /&gt;
On FreeBSD, there is an issue to build with clang 16+ the ruamel yaml clib library. You can build the FreeBSD port devel/py-ruamel.yaml.clib and copy the .whl to a stable path, then install it in your virtual environment.&lt;br /&gt;
&lt;br /&gt;
On WindRiver, the .whl is available in /opt/python/py311, so you can:&lt;br /&gt;
&lt;br /&gt;
    $ python3 -m venv /path/to/your/virtualenv&lt;br /&gt;
    $ source /path/to/your/virtualenv/bin/activate&lt;br /&gt;
    $ pip install /opt/python/py311/ruamel.yaml.clib-0.2.8-cp311-cp311-freebsd_14_0_release_p3_amd64.whl&lt;br /&gt;
    $ pip install pre-commit&lt;br /&gt;
    $ make&lt;br /&gt;
    pre-commit install&lt;br /&gt;
    pre-commit installed at .git/hooks/pre-commit&lt;br /&gt;
    $ rehash&lt;br /&gt;
    $ pre-commit&lt;br /&gt;
&lt;br /&gt;
== Refactoring ==&lt;br /&gt;
&lt;br /&gt;
=== Rename a lot of files ===&lt;br /&gt;
&lt;br /&gt;
To move a directory and rename the &#039;&#039;Source file&#039;&#039; headers:&lt;br /&gt;
&lt;br /&gt;
    git mv roles/webserver-legacy/nginx/files roles/webserver-alkane/nginx/&lt;br /&gt;
    cd roles/webserver-alkane/nginx/&lt;br /&gt;
    find . -type f -name &#039;*.conf&#039; | xargs gsed -i s/webserver-legacy/webserver-alkane/g&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
* [[/FAQ]] - Frequently asked questions about the Operations repository&lt;br /&gt;
* [[How to contribute code]]&lt;br /&gt;
* [[Devserver reference]]&lt;/div&gt;</summary>
		<author><name>Dereckson</name></author>
	</entry>
	<entry>
		<id>https://agora.nasqueron.org/index.php?title=Operations_grimoire/Operations_repository&amp;diff=2558</id>
		<title>Operations grimoire/Operations repository</title>
		<link rel="alternate" type="text/html" href="https://agora.nasqueron.org/index.php?title=Operations_grimoire/Operations_repository&amp;diff=2558"/>
		<updated>2026-07-18T20:38:54Z</updated>

		<summary type="html">&lt;p&gt;Dereckson: /* macOS */ -&amp;gt; .26&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Our configuration as code is stores in the operations (rOPS) repository.&lt;br /&gt;
&lt;br /&gt;
== Repository layout ==&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
|+ Content of rOPS&lt;br /&gt;
|-&lt;br /&gt;
! Path !! Description&lt;br /&gt;
|-&lt;br /&gt;
| _modules || Custom execution modules&lt;br /&gt;
|-&lt;br /&gt;
| _states || Custom states modules&lt;br /&gt;
|-&lt;br /&gt;
| _tests || Unit tests for custom modules, scripts, tests for repo&lt;br /&gt;
|-&lt;br /&gt;
| hotfixes || Fixes you need to run to solve a problem on the servers&lt;br /&gt;
|-&lt;br /&gt;
| pillar || Configuration data structures to use in the states&lt;br /&gt;
|-&lt;br /&gt;
| roles || The states to deploy, divided in roles and then in units&lt;br /&gt;
|-&lt;br /&gt;
| utils || Helper scripts to maintain the repository&lt;br /&gt;
|-&lt;br /&gt;
| terraform || OpenTofu / Terraform infrastructure configuration&lt;br /&gt;
|-&lt;br /&gt;
| map.jinja || As we deploy on several OS and distros, mapping of packages names or directories&lt;br /&gt;
|-&lt;br /&gt;
| top.sls || topfile: what we deploy where?&lt;br /&gt;
|-&lt;br /&gt;
| PORTS || Documentation of the ports used in the configuration&lt;br /&gt;
|-&lt;br /&gt;
| UIDs || Documentation of the users used in the configuration&lt;br /&gt;
|-&lt;br /&gt;
| GIDs || Documentation of the groups used in the configuration&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Contributions howto ==&lt;br /&gt;
=== Repository source ===&lt;br /&gt;
You&#039;ll find the Operations repository at https://devcentral.nasqueron.org/source/operations/&lt;br /&gt;
&lt;br /&gt;
If DevCentral isn&#039;t available, a mirror of the repository can be found at https://github.com/nasqueron/operations.&lt;br /&gt;
&lt;br /&gt;
=== Workflow of contributions ===&lt;br /&gt;
We follow the general workflow is described at [[How to contribute code]].&lt;br /&gt;
&lt;br /&gt;
Before committing a change to the main branch, you can test a deployment on a server.&lt;br /&gt;
In that case, merge in main immediately after the deployment as the repository is the source of truth for the server state.&lt;br /&gt;
&lt;br /&gt;
Log what you do on #nasqueron-ops, so it will be included at https://infra.nasqueron.org/servers-log/&lt;br /&gt;
&lt;br /&gt;
=== Code conventions ===&lt;br /&gt;
&#039;&#039;See also: [[Code conventions]].&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Python code: run `black` before committing&lt;br /&gt;
* YAML: indent with two spaces, including list bullets&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;yaml&amp;quot;&amp;gt;&lt;br /&gt;
id:&lt;br /&gt;
  method:&lt;br /&gt;
    - somekey: value&lt;br /&gt;
    - otherkey: value&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Environment setup ==&lt;br /&gt;
&lt;br /&gt;
Use of WindRiver is recommended if you wish to get an environment already installed for your contributions.&lt;br /&gt;
&lt;br /&gt;
=== Everywhere setup ===&lt;br /&gt;
This section cover topics needed both on our development servers or in your laptop.&lt;br /&gt;
&lt;br /&gt;
==== Python dependencies ====&lt;br /&gt;
&lt;br /&gt;
Create a virtual environment, then install dependencies from {{Ops file|requirements.txt}}:&lt;br /&gt;
&lt;br /&gt;
    mkdir -p $HOME/dev/python/ops&lt;br /&gt;
    python3 -m venv $HOME/dev/python/ops&lt;br /&gt;
    source $HOME/dev/python/ops/bin/activate&lt;br /&gt;
    pip install -r requirements.txt&lt;br /&gt;
&lt;br /&gt;
==== Datacube ====&lt;br /&gt;
&lt;br /&gt;
If you&#039;re in the ops group, you&#039;ll need sometimes to deploy from branches. As our deployment server Complector doesn&#039;t have PHP installed (so no arc), you need to exchange branches through our datacube.&lt;br /&gt;
&lt;br /&gt;
On WindRiver:&lt;br /&gt;
&lt;br /&gt;
     git remote add datacube /datacube/git/operations.git&lt;br /&gt;
&lt;br /&gt;
Anywhere else:&lt;br /&gt;
&lt;br /&gt;
     git remote add datacube ssh://windriver.nasqueron.org/datacube/git/operations.git&lt;br /&gt;
&lt;br /&gt;
If you aren&#039;t in the ops groups, and have access to our devserver, you&#039;ll still be able to clone or pull from that directory, but not to write there (ie push branches).&lt;br /&gt;
&lt;br /&gt;
=== Local computer setup ===&lt;br /&gt;
&lt;br /&gt;
This section cover topics NOT needed on our development servers.&lt;br /&gt;
&lt;br /&gt;
==== macOS ====&lt;br /&gt;
&lt;br /&gt;
To run tests properly, install first:&lt;br /&gt;
&lt;br /&gt;
    brew install bats&lt;br /&gt;
    brew install python3.13&lt;br /&gt;
&lt;br /&gt;
You can now setup the virtual environment per everywhere setup instructions.&lt;br /&gt;
&lt;br /&gt;
Salt behaves correctly on macOS, so you can install it safely in the virtual environment:&lt;br /&gt;
&lt;br /&gt;
    pip install salt==3006.26&lt;br /&gt;
&lt;br /&gt;
Check the version on WindRiver or Complector with &amp;lt;code&amp;gt;salt --versions&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Finally, to run the tests, you need a recent version of make, but the BSD make currently shipped, as of Tahoe 26.5, isn&#039;t up-to-date:&lt;br /&gt;
&lt;br /&gt;
    brew install gmake&lt;br /&gt;
    (cd _tests &amp;amp;&amp;amp; gmake)&lt;br /&gt;
&lt;br /&gt;
==== Arcanist ====&lt;br /&gt;
&lt;br /&gt;
To use arc with the operations repository, our collection of patches is needed.&lt;br /&gt;
&lt;br /&gt;
If arcanist isn&#039;t installed through Git repository, best is to do like on devserver role:&lt;br /&gt;
&lt;br /&gt;
    mkdir /opt/phabricator &amp;amp;&amp;amp; cd /opt/phabricator&lt;br /&gt;
    git clone https://github.com/nasqueron/arcanist.git&lt;br /&gt;
    (cd arcanist &amp;amp;&amp;amp; git checkout production)&lt;br /&gt;
    ln -s /opt/phabricator/arcanist/bin/arc /usr/local/bin/&lt;br /&gt;
    git clone https://devcentral.nasqueron.org/source/shellcheck-linter.git&lt;br /&gt;
&lt;br /&gt;
If you&#039;ve already cloned Arcanist repository, switch to our branch production:&lt;br /&gt;
&lt;br /&gt;
    git remote add nasqueron git@github.com:nasqueron/arcanist.git&lt;br /&gt;
    git fetch --all&lt;br /&gt;
    git checkout production&lt;br /&gt;
&lt;br /&gt;
As of August 2024, there is no plan to make that repository available on DevCentral.&lt;br /&gt;
&lt;br /&gt;
You&#039;ll also need shellcheck library-linter library, normally at the same level than your arcanist repository.&lt;br /&gt;
&lt;br /&gt;
==== IDE configuration ====&lt;br /&gt;
[[File:PyCharm-TemplateLanguages.png|thumb|right|Screenshot of correctly configured template languages]]&lt;br /&gt;
The states .sls file are Jinja2 templates producing YAML files, or &amp;quot;jinja2+yaml&amp;quot;. If this case can&#039;t be handled by your IDE, it works best to use YAML syntax highlighting.&lt;br /&gt;
&lt;br /&gt;
If you use PyCharm or IntelliJ IDEA Ultimate, you can configure this scheme:&lt;br /&gt;
&lt;br /&gt;
* Allow YAML files to be Jinja2 templates&lt;br /&gt;
** Go to Settings &amp;gt; Languages &amp;amp; Frameworks &amp;gt; Template Languages&lt;br /&gt;
** Select Jinja2 as template language&lt;br /&gt;
** Add YAML in the list&lt;br /&gt;
* Open SLS as YAML&lt;br /&gt;
&lt;br /&gt;
== Linting ==&lt;br /&gt;
&lt;br /&gt;
=== pre-commit ===&lt;br /&gt;
You can use &#039;&#039;&#039;pre-commit&#039;&#039;&#039; you can install with &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; to get a hook running Python code to lint the repository before a commit.&lt;br /&gt;
&lt;br /&gt;
Beware if you use &amp;lt;code&amp;gt;arc diff&amp;lt;/code&amp;gt; without a commit first: your message will be lost if pre-commit raises an error, always use &amp;lt;code&amp;gt;git commit&amp;lt;/code&amp;gt; first.&lt;br /&gt;
&lt;br /&gt;
On FreeBSD, there is an issue to build with clang 16+ the ruamel yaml clib library. You can build the FreeBSD port devel/py-ruamel.yaml.clib and copy the .whl to a stable path, then install it in your virtual environment.&lt;br /&gt;
&lt;br /&gt;
On WindRiver, the .whl is available in /opt/python/py311, so you can:&lt;br /&gt;
&lt;br /&gt;
    $ python3 -m venv /path/to/your/virtualenv&lt;br /&gt;
    $ source /path/to/your/virtualenv/bin/activate&lt;br /&gt;
    $ pip install /opt/python/py311/ruamel.yaml.clib-0.2.8-cp311-cp311-freebsd_14_0_release_p3_amd64.whl&lt;br /&gt;
    $ pip install pre-commit&lt;br /&gt;
    $ make&lt;br /&gt;
    pre-commit install&lt;br /&gt;
    pre-commit installed at .git/hooks/pre-commit&lt;br /&gt;
    $ rehash&lt;br /&gt;
    $ pre-commit&lt;br /&gt;
&lt;br /&gt;
== Refactoring ==&lt;br /&gt;
&lt;br /&gt;
=== Rename a lot of files ===&lt;br /&gt;
&lt;br /&gt;
To move a directory and rename the &#039;&#039;Source file&#039;&#039; headers:&lt;br /&gt;
&lt;br /&gt;
    git mv roles/webserver-legacy/nginx/files roles/webserver-alkane/nginx/&lt;br /&gt;
    cd roles/webserver-alkane/nginx/&lt;br /&gt;
    find . -type f -name &#039;*.conf&#039; | xargs gsed -i s/webserver-legacy/webserver-alkane/g&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
* [[/FAQ]] - Frequently asked questions about the Operations repository&lt;br /&gt;
* [[How to contribute code]]&lt;br /&gt;
* [[Devserver reference]]&lt;/div&gt;</summary>
		<author><name>Dereckson</name></author>
	</entry>
	<entry>
		<id>https://agora.nasqueron.org/index.php?title=Operations_grimoire/External_services&amp;diff=2557</id>
		<title>Operations grimoire/External services</title>
		<link rel="alternate" type="text/html" href="https://agora.nasqueron.org/index.php?title=Operations_grimoire/External_services&amp;diff=2557"/>
		<updated>2026-07-05T13:16:15Z</updated>

		<summary type="html">&lt;p&gt;Dereckson: /* JetBrains */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Amazon Web Services (AWS) ==&lt;br /&gt;
S3, account managed by Sandlayth.&lt;br /&gt;
&lt;br /&gt;
== Docker Hub ==&lt;br /&gt;
Organization account, administrative access by Sandlayth and Dereckson.&lt;br /&gt;
&lt;br /&gt;
2021-09-12: request for open source as part of the https://www.docker.com/blog/expanded-support-for-open-source-software-projects done, mainly as automated builds have been disabled in the free team plan.&lt;br /&gt;
&lt;br /&gt;
== GeoLite2 ==&lt;br /&gt;
Account at MaxMind for GeoLite2 databases, created by Dereckson.&lt;br /&gt;
&lt;br /&gt;
Account credentials stored in Vault under &amp;lt;code&amp;gt;ops/infra/maxmind&amp;lt;/code&amp;gt;.&lt;br /&gt;
There aren&#039;t the API credentials, for example Sentry ones are stored at &amp;lt;code&amp;gt;ops/secrets/nasqueron/sentry/geoipupdate&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Gandi ==&lt;br /&gt;
Some domains names:&lt;br /&gt;
* eglide.org, account managed by Sandlayth&lt;br /&gt;
* ook.space, account managed by Dereckson&lt;br /&gt;
&lt;br /&gt;
== GitHub ==&lt;br /&gt;
;Organization account&lt;br /&gt;
:Administrative access by Sandlayth and Dereckson&lt;br /&gt;
:&#039;&#039;Some OAuth could be on Dereckson account. When found, should be switched to Nasqueron (see [https://devcentral.nasqueron.org/T1109 T1109]).&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
;Alken-Orin&lt;br /&gt;
:As automated agent, there is an &#039;&#039;&#039;Alken-Orin&#039;&#039;&#039; account to link GitHub to CI/CD.&lt;br /&gt;
:This account is also used to fetch code from GitHub through the `staging_private_repository` Salt state. To that end, the Salt deploy SSH key is added to this account.&lt;br /&gt;
:Credentials at [https://devcentral.nasqueron.org/K53 K53].&lt;br /&gt;
&lt;br /&gt;
== Google ==&lt;br /&gt;
OAuth for DevCentral, account managed by Dereckson (under espace-win.org Google Apps organization)&lt;br /&gt;
&lt;br /&gt;
== Hurricane Electric ==&lt;br /&gt;
IPv6 connectivity, DNS for nasqueron.org: account &#039;nasqueron&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; DNS for some other domains are currently handled on the &#039;dereckson&#039; account, they&#039;ll be moved to &#039;nasqueron&#039; account when defined as secondary.&lt;br /&gt;
&lt;br /&gt;
== instances.mastodon.xyz ==&lt;br /&gt;
Credentials for this account are stored in [https://devcentral.nasqueron.org/K103 K103].&lt;br /&gt;
&lt;br /&gt;
== JetBrains ==&lt;br /&gt;
Licenses for open-source contributions in the nasqueron organization.&lt;br /&gt;
&lt;br /&gt;
Have access as org admins: Dereckson, Dorian.&lt;br /&gt;
&lt;br /&gt;
== Mailgun ==&lt;br /&gt;
Account managed by Dereckson.&lt;br /&gt;
&lt;br /&gt;
2020-02-28: account upgraded to Flex, as it&#039;s not possible anymore to add custom domains to the free plan. From July, mails will cost 0.80$ / 1000. To avoid any financial abuse, (i) a 1000 mail accounts limit is currently in (we can update it in account settings) (ii) the credit card associated for this account is limited to 5 € / month.&lt;br /&gt;
&lt;br /&gt;
== Microsoft ==&lt;br /&gt;
=== Reporting for mail sent to Outlook.com ===&lt;br /&gt;
For mail reporting, Outlook.com offers a &amp;quot;[https://sendersupport.olc.protection.outlook.com/ Smart Network Data Service]&amp;quot; to report statistics about abused IP.&lt;br /&gt;
&lt;br /&gt;
Any op can subscribe with their own Microsoft account on https://sendersupport.olc.protection.outlook.com/snds/addnetwork.aspx / authorization request should ideally be sent to postmaster for tracking.&lt;br /&gt;
&lt;br /&gt;
It&#039;s also configured to send report about mails marked as spam by Outlook users to postmaster.&lt;br /&gt;
&lt;br /&gt;
== Mural ==&lt;br /&gt;
Mural non-profit plan for Wolfplex Hackerspace ASBL, Sébastien has access.&lt;br /&gt;
&lt;br /&gt;
Personal notes:&lt;br /&gt;
* We have 10 seats&lt;br /&gt;
* To add an user: [https://app.mural.co/t/nasqueron8788/settings/members workspace &amp;gt; settings &amp;gt; members]&lt;br /&gt;
* Mail about access requests go to Wolfplex mail&lt;br /&gt;
&lt;br /&gt;
== PURL ==&lt;br /&gt;
/NET/Nasqueron is managed by the Dereckson Internet Archive account.&lt;br /&gt;
&lt;br /&gt;
== Online / Scaleway ==&lt;br /&gt;
;Online&lt;br /&gt;
* [[Ysul]], account managed by Dereckson, billed to Dereckson&lt;br /&gt;
* [[WindRiver]], account managed by Dereckson, billed to Trantorium&lt;br /&gt;
;Scaleway&lt;br /&gt;
* [[Eglide]], account managed by Sandlayth, billed to Sandlayth&lt;br /&gt;
** Following organization account introduction, Dereckson has now access too.&lt;br /&gt;
&lt;br /&gt;
== OVH / SoYouStart ==&lt;br /&gt;
Servers:&lt;br /&gt;
* [[hyper-001]], account managed by Dereckson, billed to ?&lt;br /&gt;
* [[CloudHugger]], account managed by Dereckson, billed to Trantorium&lt;br /&gt;
&lt;br /&gt;
Registrar for nasqueron.org and nasqueron-user-content.org&lt;br /&gt;
&lt;br /&gt;
== Sendgrid ==&lt;br /&gt;
Account managed by Dereckson.&lt;br /&gt;
&lt;br /&gt;
== Wikimedia ==&lt;br /&gt;
OAuth authentication, managed by Dereckson&lt;/div&gt;</summary>
		<author><name>Dereckson</name></author>
	</entry>
	<entry>
		<id>https://agora.nasqueron.org/index.php?title=Operations_grimoire/External_services&amp;diff=2556</id>
		<title>Operations grimoire/External services</title>
		<link rel="alternate" type="text/html" href="https://agora.nasqueron.org/index.php?title=Operations_grimoire/External_services&amp;diff=2556"/>
		<updated>2026-07-05T13:16:08Z</updated>

		<summary type="html">&lt;p&gt;Dereckson: /* JetBrains */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Amazon Web Services (AWS) ==&lt;br /&gt;
S3, account managed by Sandlayth.&lt;br /&gt;
&lt;br /&gt;
== Docker Hub ==&lt;br /&gt;
Organization account, administrative access by Sandlayth and Dereckson.&lt;br /&gt;
&lt;br /&gt;
2021-09-12: request for open source as part of the https://www.docker.com/blog/expanded-support-for-open-source-software-projects done, mainly as automated builds have been disabled in the free team plan.&lt;br /&gt;
&lt;br /&gt;
== GeoLite2 ==&lt;br /&gt;
Account at MaxMind for GeoLite2 databases, created by Dereckson.&lt;br /&gt;
&lt;br /&gt;
Account credentials stored in Vault under &amp;lt;code&amp;gt;ops/infra/maxmind&amp;lt;/code&amp;gt;.&lt;br /&gt;
There aren&#039;t the API credentials, for example Sentry ones are stored at &amp;lt;code&amp;gt;ops/secrets/nasqueron/sentry/geoipupdate&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Gandi ==&lt;br /&gt;
Some domains names:&lt;br /&gt;
* eglide.org, account managed by Sandlayth&lt;br /&gt;
* ook.space, account managed by Dereckson&lt;br /&gt;
&lt;br /&gt;
== GitHub ==&lt;br /&gt;
;Organization account&lt;br /&gt;
:Administrative access by Sandlayth and Dereckson&lt;br /&gt;
:&#039;&#039;Some OAuth could be on Dereckson account. When found, should be switched to Nasqueron (see [https://devcentral.nasqueron.org/T1109 T1109]).&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
;Alken-Orin&lt;br /&gt;
:As automated agent, there is an &#039;&#039;&#039;Alken-Orin&#039;&#039;&#039; account to link GitHub to CI/CD.&lt;br /&gt;
:This account is also used to fetch code from GitHub through the `staging_private_repository` Salt state. To that end, the Salt deploy SSH key is added to this account.&lt;br /&gt;
:Credentials at [https://devcentral.nasqueron.org/K53 K53].&lt;br /&gt;
&lt;br /&gt;
== Google ==&lt;br /&gt;
OAuth for DevCentral, account managed by Dereckson (under espace-win.org Google Apps organization)&lt;br /&gt;
&lt;br /&gt;
== Hurricane Electric ==&lt;br /&gt;
IPv6 connectivity, DNS for nasqueron.org: account &#039;nasqueron&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; DNS for some other domains are currently handled on the &#039;dereckson&#039; account, they&#039;ll be moved to &#039;nasqueron&#039; account when defined as secondary.&lt;br /&gt;
&lt;br /&gt;
== instances.mastodon.xyz ==&lt;br /&gt;
Credentials for this account are stored in [https://devcentral.nasqueron.org/K103 K103].&lt;br /&gt;
&lt;br /&gt;
== JetBrains ==&lt;br /&gt;
Licenses for open-source contributions in the nasqueron organization.&lt;br /&gt;
&lt;br /&gt;
Have access: Dereckson, Dorian.&lt;br /&gt;
&lt;br /&gt;
== Mailgun ==&lt;br /&gt;
Account managed by Dereckson.&lt;br /&gt;
&lt;br /&gt;
2020-02-28: account upgraded to Flex, as it&#039;s not possible anymore to add custom domains to the free plan. From July, mails will cost 0.80$ / 1000. To avoid any financial abuse, (i) a 1000 mail accounts limit is currently in (we can update it in account settings) (ii) the credit card associated for this account is limited to 5 € / month.&lt;br /&gt;
&lt;br /&gt;
== Microsoft ==&lt;br /&gt;
=== Reporting for mail sent to Outlook.com ===&lt;br /&gt;
For mail reporting, Outlook.com offers a &amp;quot;[https://sendersupport.olc.protection.outlook.com/ Smart Network Data Service]&amp;quot; to report statistics about abused IP.&lt;br /&gt;
&lt;br /&gt;
Any op can subscribe with their own Microsoft account on https://sendersupport.olc.protection.outlook.com/snds/addnetwork.aspx / authorization request should ideally be sent to postmaster for tracking.&lt;br /&gt;
&lt;br /&gt;
It&#039;s also configured to send report about mails marked as spam by Outlook users to postmaster.&lt;br /&gt;
&lt;br /&gt;
== Mural ==&lt;br /&gt;
Mural non-profit plan for Wolfplex Hackerspace ASBL, Sébastien has access.&lt;br /&gt;
&lt;br /&gt;
Personal notes:&lt;br /&gt;
* We have 10 seats&lt;br /&gt;
* To add an user: [https://app.mural.co/t/nasqueron8788/settings/members workspace &amp;gt; settings &amp;gt; members]&lt;br /&gt;
* Mail about access requests go to Wolfplex mail&lt;br /&gt;
&lt;br /&gt;
== PURL ==&lt;br /&gt;
/NET/Nasqueron is managed by the Dereckson Internet Archive account.&lt;br /&gt;
&lt;br /&gt;
== Online / Scaleway ==&lt;br /&gt;
;Online&lt;br /&gt;
* [[Ysul]], account managed by Dereckson, billed to Dereckson&lt;br /&gt;
* [[WindRiver]], account managed by Dereckson, billed to Trantorium&lt;br /&gt;
;Scaleway&lt;br /&gt;
* [[Eglide]], account managed by Sandlayth, billed to Sandlayth&lt;br /&gt;
** Following organization account introduction, Dereckson has now access too.&lt;br /&gt;
&lt;br /&gt;
== OVH / SoYouStart ==&lt;br /&gt;
Servers:&lt;br /&gt;
* [[hyper-001]], account managed by Dereckson, billed to ?&lt;br /&gt;
* [[CloudHugger]], account managed by Dereckson, billed to Trantorium&lt;br /&gt;
&lt;br /&gt;
Registrar for nasqueron.org and nasqueron-user-content.org&lt;br /&gt;
&lt;br /&gt;
== Sendgrid ==&lt;br /&gt;
Account managed by Dereckson.&lt;br /&gt;
&lt;br /&gt;
== Wikimedia ==&lt;br /&gt;
OAuth authentication, managed by Dereckson&lt;/div&gt;</summary>
		<author><name>Dereckson</name></author>
	</entry>
	<entry>
		<id>https://agora.nasqueron.org/index.php?title=Dev_zone/JetBrains_licenses&amp;diff=2555</id>
		<title>Dev zone/JetBrains licenses</title>
		<link rel="alternate" type="text/html" href="https://agora.nasqueron.org/index.php?title=Dev_zone/JetBrains_licenses&amp;diff=2555"/>
		<updated>2026-07-05T13:14:56Z</updated>

		<summary type="html">&lt;p&gt;Dereckson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;JetBrains &amp;quot;supports non-commercial open source projects&amp;quot; with access to all IDE in an all product pack license, restricted to open source contributions. More information are available at https://jb.gg/OpenSourceSupport.&lt;br /&gt;
&lt;br /&gt;
== How to get a license? ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;We currently need to renew a license request, so you can&#039;t get one now, but please let us know if you&#039;re interested.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You can contact [[User:Dereckson|Dereckson]] for a license. According JetBrains conditions, licenses are available for &amp;quot;regular contributions to the project for at least a few months&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
There is no minimal threshold of contributions, we welcome any contributions rhythm.&lt;br /&gt;
&lt;br /&gt;
Licenses can be used for any IDE, IntelliJ IDEA or a specific one like PhpStorm, WebStorm or PyCharm.&lt;br /&gt;
&lt;br /&gt;
[[Category:Contributor guide]]&lt;/div&gt;</summary>
		<author><name>Dereckson</name></author>
	</entry>
	<entry>
		<id>https://agora.nasqueron.org/index.php?title=Operations_grimoire/PostgreSQL&amp;diff=2554</id>
		<title>Operations grimoire/PostgreSQL</title>
		<link rel="alternate" type="text/html" href="https://agora.nasqueron.org/index.php?title=Operations_grimoire/PostgreSQL&amp;diff=2554"/>
		<updated>2026-07-05T12:57:35Z</updated>

		<summary type="html">&lt;p&gt;Dereckson: /* Upgrade */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;PostgreSQL is available as a standalone role and can also be enabled on devserver.&lt;br /&gt;
&lt;br /&gt;
Applications on the Docker PaaS can use our PostgreSQL infrastructure (Airflow, datasources) or have their own container (Sentry, with custom wal2json extension). This resource documents our own db- servers.&lt;br /&gt;
&lt;br /&gt;
== Howto ==&lt;br /&gt;
&lt;br /&gt;
=== Open a console === &lt;br /&gt;
Use peer authentication from the postgres user: &amp;lt;code&amp;gt;sudo -u postgres psql&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Run queries against database ===&lt;br /&gt;
The important things are:&lt;br /&gt;
&lt;br /&gt;
# prepare the operation with a .sql file&lt;br /&gt;
# put that SQL file to a task&lt;br /&gt;
# avoid data destruction and allow rollback&lt;br /&gt;
## if a table needs to be dropped, we can rename it to _unused&lt;br /&gt;
## if an application doesn&#039;t use a column anymore, we can rename it from foo to foo_unused so we can rollback by renaming back&lt;br /&gt;
## actual deletion can be done some weeks later&lt;br /&gt;
&lt;br /&gt;
Recommend procedure:&lt;br /&gt;
&lt;br /&gt;
# Create a task on DevCentral or reuse an existing deployment task&lt;br /&gt;
# Upload the .sql file on DevCentral or to a repository:&lt;br /&gt;
## One-shot maintenance can go to https://devcentral.nasqueron.org/paste/ or sent with &amp;lt;code&amp;gt;cat foo.sql | arc paste --title foo.sql --&amp;lt;/code&amp;gt;&lt;br /&gt;
## Regular queries can go to the [https://devcentral.nasqueron.org/source/reports/browse/main/sql/ reports repository]&lt;br /&gt;
# Link it in the task&lt;br /&gt;
# Run it&lt;br /&gt;
&lt;br /&gt;
To run foo.sql against acme database:&lt;br /&gt;
&lt;br /&gt;
# upload the foo.sql file to the relevant server (for example db-A-001 for db-A cluster)&lt;br /&gt;
# &amp;lt;code&amp;gt;sudo -u postgres psql acme &amp;lt; foo.sql&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Create a new database or user ===&lt;br /&gt;
&lt;br /&gt;
It&#039;s a simple two steps process:&lt;br /&gt;
&lt;br /&gt;
# Edit the relevant pillar file, for example pillar/dbserver/cluster-A.sls in rOPS&lt;br /&gt;
# Deploy the change: &amp;lt;code&amp;gt;salt db-A-001 state.apply roles/dbserver-pgsql&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You generally need:&lt;br /&gt;
&lt;br /&gt;
* an user block in dbserver_postgresql.users&lt;br /&gt;
** block title is the username&lt;br /&gt;
** a password needs to be set in Flow, key is under ops/secrets/&lt;br /&gt;
* a database block&lt;br /&gt;
* a connection triplet db, user, ips (use /32 for an unique IP)&lt;br /&gt;
&lt;br /&gt;
By default, external connections are NOT enabled for any user and database, an entry for pg_hba.conf MUST be added in connections part.&lt;br /&gt;
&lt;br /&gt;
Servers don&#039;t have a public ICANN IP, so you can only connect from other Nasqueron servers.&lt;br /&gt;
&lt;br /&gt;
=== Grant privileges to an user ===&lt;br /&gt;
&lt;br /&gt;
Some applications don&#039;t set privileges, even if they own the database. That&#039;s for example the case of Orbeon Forms DDL.&lt;br /&gt;
&lt;br /&gt;
To determine if acme has already the rights on the database:&lt;br /&gt;
&lt;br /&gt;
    SELECT grantor, grantee, table_schema, table_name, privilege_type&lt;br /&gt;
    FROM information_schema.table_privileges&lt;br /&gt;
    WHERE grantee = &#039;acme&#039;;&lt;br /&gt;
&lt;br /&gt;
If not:&lt;br /&gt;
&lt;br /&gt;
    GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO acme;&lt;br /&gt;
&lt;br /&gt;
This set of privileges can be handled directly by Salt in cluster privileges definition:&lt;br /&gt;
&lt;br /&gt;
      privileges:&lt;br /&gt;
        - database: &amp;lt;database name&amp;gt;&lt;br /&gt;
          scope: table&lt;br /&gt;
          schema: public&lt;br /&gt;
          tables:&lt;br /&gt;
            - ALL&lt;br /&gt;
          privileges:&lt;br /&gt;
            - ALL&lt;br /&gt;
&lt;br /&gt;
See {{D|3252}} or {{D|3253}} for an example.&lt;br /&gt;
&lt;br /&gt;
As a known issue, this query will ALWAYS be executed by Salt.&lt;br /&gt;
&lt;br /&gt;
; Sequences privileges&lt;br /&gt;
&lt;br /&gt;
Sequences aren&#039;t included in that GRANT ALL PRIVILEGES. We can generate GRANT queries for them:&lt;br /&gt;
&lt;br /&gt;
    SELECT &#039;GRANT USAGE ON SEQUENCE &#039; || sequence_schema || &#039;.&#039; || sequence_name || &#039; TO &amp;quot;acme&amp;quot;;&#039;&lt;br /&gt;
    FROM information_schema.sequences&lt;br /&gt;
    WHERE sequence_schema NOT LIKE &#039;pg_%&#039;&lt;br /&gt;
    AND sequence_schema != &#039;information_schema&#039;;&lt;br /&gt;
&lt;br /&gt;
=== What to do after an update of PostgreSQL servers? ===&lt;br /&gt;
&lt;br /&gt;
The following services need their connection to explicitly be restarted:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Services to tweak&lt;br /&gt;
|-&lt;br /&gt;
! Cluster !! Service !! Procedure&lt;br /&gt;
|-&lt;br /&gt;
| A || Airflow &amp;gt; airflow_triggerer || On Dwellers, docker restart airflow_triggerer&lt;br /&gt;
|-&lt;br /&gt;
| A || Airflow &amp;gt; airflow_scheduler || On Dwellers, docker restart airflow_scheduler&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Upgrade ==&lt;br /&gt;
=== PostgreSQL package ===&lt;br /&gt;
When upgrading PostgreSQL the following checks must be done:&lt;br /&gt;
&lt;br /&gt;
* Do we have the postgres -contrib port installed too for the pg_trgm module for FANTOIR?&lt;br /&gt;
* Do we have XML support for Orbeon?&lt;br /&gt;
&lt;br /&gt;
There are several methods to upgrade a server:&lt;br /&gt;
* the pg_dumpall method has been successfully tested on WindRiver for 15 -&amp;gt; 16&lt;br /&gt;
* the pg_upgrade method has been used for 16 -&amp;gt; 17 and 17 -&amp;gt; 18&lt;br /&gt;
&lt;br /&gt;
=== pg_upgrade ===&lt;br /&gt;
&lt;br /&gt;
This procedure describes an in-place upgrade of PostgreSQL using pg_upgrade on FreeBSD with ZFS available.&lt;br /&gt;
&lt;br /&gt;
The example below upgrades PostgreSQL 17 to PostgreSQL 18, while preserving the old cluster for rollback. Tested on WindRiver.&lt;br /&gt;
&lt;br /&gt;
;Preconditions&lt;br /&gt;
* PostgreSQL 17 cluster is located at: &amp;lt;code&amp;gt;/var/db/postgres/data17&amp;lt;/code&amp;gt;&lt;br /&gt;
* A new ZFS dataset will be created for PostgreSQL 18 at &amp;lt;code&amp;gt;arcology/postgresql/data18&amp;lt;/code&amp;gt;&lt;br /&gt;
* PostgreSQL 17 package is available in cache in &amp;lt;code&amp;gt;/var/cache/pkg/&amp;lt;/code&amp;gt;&lt;br /&gt;
* PostgreSQL service will need to be stopped before starting the actual upgrade procedure &lt;br /&gt;
&lt;br /&gt;
; Create new data directory&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sh&amp;quot;&amp;gt;&lt;br /&gt;
$ pkg install postgresql18-server postgresql18-client postgresql18-contrib&lt;br /&gt;
$ zfs create \&lt;br /&gt;
  -o mountpoint=/var/db/postgres/data18 \&lt;br /&gt;
  -o compression=lz4 \&lt;br /&gt;
  -o atime=off \&lt;br /&gt;
  -o recordsize=8K \&lt;br /&gt;
  arcology/postgresql/data18&lt;br /&gt;
$ chown postgres:postgres /data18&lt;br /&gt;
$ chmod 700 /data18&lt;br /&gt;
$ sudo -u postgres initdb --no-data-checksums -D /var/db/postgres/data18&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; Extract old version packages and do a dry-run&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sh&amp;quot;&amp;gt;&lt;br /&gt;
$ rm -rf /tmp/pg-upgrade &amp;amp;&amp;amp; mkdir /tmp/pg-upgrade&lt;br /&gt;
$ cd /var/cache/pkg&lt;br /&gt;
$ tar xf postgresql17-server-17.10.pkg -C /tmp/pg-upgrade&lt;br /&gt;
$ tar xf postgresql17-contrib-17.10.pkg -C /tmp/pg-upgrade&lt;br /&gt;
$ /tmp/pg-upgrade/usr/local/bin/postgres --version&lt;br /&gt;
postgres (PostgreSQL) 17.10&lt;br /&gt;
$ sudo -u postgres pg_upgrade \&lt;br /&gt;
  --check \&lt;br /&gt;
  -b /tmp/pg-upgrade/usr/local/bin \&lt;br /&gt;
  -B /usr/local/bin \&lt;br /&gt;
  -d /var/db/postgres/data17 \&lt;br /&gt;
  -D /var/db/postgres/data18&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this stage, it&#039;s needed to resolve issues reported by pg_upgrade.&lt;br /&gt;
&lt;br /&gt;
; Upgrade&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
$ service postgresql stop&lt;br /&gt;
$ sudo -u postgres pg_upgrade \&lt;br /&gt;
  -b /tmp/pg-upgrade/usr/local/bin \&lt;br /&gt;
  -B /usr/local/bin \&lt;br /&gt;
  -d /var/db/postgres/data17 \&lt;br /&gt;
  -D /var/db/postgres/data18&lt;br /&gt;
$ cd /var/db/postgres&lt;br /&gt;
$ rm data&lt;br /&gt;
$ ln -s data18 data&lt;br /&gt;
$ service postgresql start&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; Post-upgrade maintenance&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sh&amp;quot;&amp;gt;&lt;br /&gt;
$ sudo -u postgres vacuumdb --all --analyze-in-stages --missing-stats-only&lt;br /&gt;
$ sudo -u postgres vacuumdb --all --analyze-only&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If a file update_extensions.sql has been created, run it to update extensions schema.&lt;br /&gt;
&lt;br /&gt;
=== Rollback procedure for pg_upgrade ===&lt;br /&gt;
&lt;br /&gt;
# Remove current version packages&lt;br /&gt;
# Reinstall old version packages&lt;br /&gt;
# Stop server&lt;br /&gt;
# Resymlink the old data directory as /var/db/postgres/data&lt;br /&gt;
# Start server&lt;br /&gt;
&lt;br /&gt;
== Clusters ==&lt;br /&gt;
&lt;br /&gt;
Letters can be discontinuous: for example, B will be a MySQL cluster.&lt;br /&gt;
&lt;br /&gt;
=== Cluster A ===&lt;br /&gt;
A is the general cluster, for Nasqueron services. It currently has one server, db-A-001.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Databases&lt;br /&gt;
|-&lt;br /&gt;
! Database !! Managed by !! Description&lt;br /&gt;
|-&lt;br /&gt;
| airflow || Nasqueron Ops || Workflows runner, used by datasources&lt;br /&gt;
|-&lt;br /&gt;
| fantoir || Datasources || PostgreSQL version of FANTOIR for geocoding&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Troubleshoot ==&lt;br /&gt;
=== An application stops to work correctly with PostgreSQL ===&lt;br /&gt;
Issues with queries are logged to /var/log/messages:&lt;br /&gt;
&lt;br /&gt;
    $ tail -n100 -f /var/log/messages | grep postgres&lt;br /&gt;
&lt;br /&gt;
For example, {{T|1943}} issue was found with this line:&lt;br /&gt;
&lt;br /&gt;
    Jan 14 23:13:58 db-A-001 postgres[35351]: [8-1] 2024-01-14 23:13:58.081 UTC [35351] ERROR:  unsupported XML feature&lt;br /&gt;
&lt;br /&gt;
=== Unsupported XML feature ===&lt;br /&gt;
For Orbeon, XML support is required. That&#039;s not by default the case on FreeBSD, the port needs to be built manually. That&#039;s the case when provisioning a new server through {{Ops file|roles/dbserver-pgsql/server/build.sls}} but upgrade can break this port.&lt;br /&gt;
&lt;br /&gt;
If so, rebuild the package. For that, you can follow the instructions of [[Operations grimoire/FreeBSD]], section PostgreSQL. &lt;br /&gt;
&lt;br /&gt;
=== Some postgres_privileges.present are always changed by Salt ===&lt;br /&gt;
&lt;br /&gt;
Some ON ALL TABLE privilege queries are always run by the Salt PostgreSQL execution module. For example:&lt;br /&gt;
&lt;br /&gt;
          ID: dbserver_pgsql_user_orbeon_privilege_2_ALL&lt;br /&gt;
    Function: postgres_privileges.present&lt;br /&gt;
        Name: orbeon&lt;br /&gt;
      Result: True&lt;br /&gt;
     Comment: The privilege(s): ALL have been granted to orbeon&lt;br /&gt;
     Started: 21:54:53.656120&lt;br /&gt;
    Duration: 284.394 ms&lt;br /&gt;
     Changes:   &lt;br /&gt;
              ----------&lt;br /&gt;
              orbeon:&lt;br /&gt;
                  Present&lt;br /&gt;
&lt;br /&gt;
Those statements aren&#039;t idempotent. This is a known issue, and doesn&#039;t affect deployment.&lt;/div&gt;</summary>
		<author><name>Dereckson</name></author>
	</entry>
	<entry>
		<id>https://agora.nasqueron.org/index.php?title=Operations_grimoire/NetBox&amp;diff=2553</id>
		<title>Operations grimoire/NetBox</title>
		<link rel="alternate" type="text/html" href="https://agora.nasqueron.org/index.php?title=Operations_grimoire/NetBox&amp;diff=2553"/>
		<updated>2026-07-05T10:01:36Z</updated>

		<summary type="html">&lt;p&gt;Dereckson: /* Python */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;NetBox is the current source of truth for the network. It&#039;s available at [https://netbox.nasqueron.org NetBox].&lt;br /&gt;
&lt;br /&gt;
== Integration with Salt ==&lt;br /&gt;
Ongoing integration projects are in work to serve NetBox data as part of Salt pillar for configuration as code.&lt;br /&gt;
&lt;br /&gt;
It should serve:&lt;br /&gt;
* /etc/hosts data for Drake network machines&lt;br /&gt;
* the same information available at pillar/nodes/nodes.sls, so we won&#039;t need to maintain that anymore&lt;br /&gt;
&lt;br /&gt;
== Integration with IRC ==&lt;br /&gt;
Export to a database for [[Odderon]] is discussed at [https://devcentral.nasqueron.org/T1868 T1868].&lt;br /&gt;
&lt;br /&gt;
That should allow the following workflow:&lt;br /&gt;
&lt;br /&gt;
    17:13:59 &amp;lt; Dereckson&amp;gt; 172.27.27.6&lt;br /&gt;
    17:14:00 &amp;lt; Odderon&amp;gt; (Dereckson): 172.27.27.6/28 docker-001.nasqueron.org / Decommissioned address for docker-001.nasqueron.org / Drake [deprecated]&lt;br /&gt;
&lt;br /&gt;
Source code of the translation code is available at https://devcentral.nasqueron.org/source/netbox-darkbot-db/&lt;br /&gt;
&lt;br /&gt;
== Backup ==&lt;br /&gt;
To backup the PostgreSQL database:&lt;br /&gt;
&lt;br /&gt;
    sudo -u postgres pg_dump netbox | gzip &amp;gt; netbox-$(date +&amp;quot;%Y-%m-%d&amp;quot;).gz&lt;br /&gt;
&lt;br /&gt;
Database is currently hosted on WindRiver, not on DB-A, even if a user exists there and an outdated copy exists.&lt;br /&gt;
&lt;br /&gt;
== Upgrade ==&lt;br /&gt;
=== NetBox ===&lt;br /&gt;
To upgrade NetBox:&lt;br /&gt;
# Backup database on WindRiver&lt;br /&gt;
# Install the new version&lt;br /&gt;
# Copy configuration&lt;br /&gt;
# Update Python dependencies&lt;br /&gt;
# Shutdown the service: &amp;lt;code&amp;gt;service netbox stop&amp;lt;/code&amp;gt; or if pid is wrong &amp;lt;code&amp;gt;killall netbox&amp;lt;/code&amp;gt;&lt;br /&gt;
# Symlink the directory in /srv/netbox&lt;br /&gt;
# Run the database migrations and regenerate static resources, etc. as documented in upgrade.sh&lt;br /&gt;
# Start the service&lt;br /&gt;
&lt;br /&gt;
An example for upgrade to 3.7.0:&lt;br /&gt;
&lt;br /&gt;
    sudo -u postgres pg_dump netbox | gzip &amp;gt; netbox-$(date +&amp;quot;%Y-%m-%d&amp;quot;).gz&lt;br /&gt;
    cd /srv/netbox&lt;br /&gt;
    wget https://github.com/netbox-community/netbox/archive/refs/tags/v3.7.0.tar.gz&lt;br /&gt;
    tar xzf v3.7.0.tar.gz&lt;br /&gt;
    cp /srv/netbox/netbox/netbox/netbox/configuration.py netbox-3.7.0/netbox/netbox/&lt;br /&gt;
    source venv/bin/activate&lt;br /&gt;
    pip install -r netbox-3.7.0/requirements.txt&lt;br /&gt;
    killall -u netbox&lt;br /&gt;
    rm netbox&lt;br /&gt;
    ln -s netbox-3.7.0 netbox&lt;br /&gt;
    cd /srv/netbox/netbox&lt;br /&gt;
    mkdocs build&lt;br /&gt;
    cd /srv/netbox/netbox/netbox&lt;br /&gt;
    python3 manage.py migrate&lt;br /&gt;
    python3 manage.py collectstatic&lt;br /&gt;
    python3 manage.py remove_stale_contenttypes&lt;br /&gt;
    python3 manage.py reindex --lazy&lt;br /&gt;
    python3 manage.py clearsessions&lt;br /&gt;
    service netbox start&lt;br /&gt;
&lt;br /&gt;
To track configuration changes, you can use https://github.com/netbox-community/netbox/commits/develop/netbox/netbox/configuration_example.py&lt;br /&gt;
&lt;br /&gt;
If psycopg can&#039;t build, you can build it with &amp;lt;code&amp;gt;pip install &amp;quot;psycopg[c]&amp;quot;&amp;lt;/code&amp;gt;. That requires development headers for PostgreSQL, available on all FreeBSD servers where PostgreSQL is installed ; for a Docker image based on Linux, search for a libpq-dev or libpq-devel package for that purpose.&lt;br /&gt;
&lt;br /&gt;
Documentation needs to be generated before collectstatic. If not, run again the collectstatic command to copy docs from project-static to static directory.&lt;br /&gt;
&lt;br /&gt;
=== Python ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;This procedure only applies when we do major interpreter change (e.g. Python 3.11 to 3.12) at OS level.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
To recreate the virtual environment with a new Python interpreter, recreate as root an empty venv directory:&lt;br /&gt;
&lt;br /&gt;
    rm -rf /srv/netbox/venv&lt;br /&gt;
    mkdir /srv/netbox/venv&lt;br /&gt;
    chown netbox:netbox /srv/netbox/venv&lt;br /&gt;
&lt;br /&gt;
Then, as netbox user, recreate it:&lt;br /&gt;
&lt;br /&gt;
    python3 -m venv /srv/netbox/venv&lt;br /&gt;
    source /srv/netbox/venv/bin/activate&lt;br /&gt;
    pip install --upgrade pip&lt;br /&gt;
    pip install -r /srv/netbox/netbox/requirements.txt&lt;br /&gt;
&lt;br /&gt;
If you&#039;ve any issue with psycopg, you can build them from FreeBSD ports and copy the .whl to /opt/python/py312 or your version folder.&lt;br /&gt;
&lt;br /&gt;
    $ ls /opt/python/py312&lt;br /&gt;
    psycopg_c-3.2.13-cp312-cp312-freebsd_15_1_release_p1_amd64.whl  psycopg_pool-3.3.1-py3-none-any.whl                             psycopg-3.2.13-py3-none-any.whl&lt;br /&gt;
    $ pip install /opt/python/py312/psycopg*&lt;br /&gt;
&lt;br /&gt;
To easily find and copy the .whl from your port folder:&lt;br /&gt;
&lt;br /&gt;
    cp $(find . -type f -name &#039;*.whl&#039;) /opt/python/py312/&lt;br /&gt;
&lt;br /&gt;
== Troubleshoot ==&lt;br /&gt;
=== Grafana ===&lt;br /&gt;
&lt;br /&gt;
Use [https://grafana.nasqueron.org/d/O6v4rMpizda/netbox?orgId=1&amp;amp;refresh=10s Grafana dashboard] to check statistics.&lt;br /&gt;
&lt;br /&gt;
As of 2024-08-04, all the rates are erroneous and (a lot) over-evaluated.&lt;br /&gt;
&lt;br /&gt;
=== 500 after server reboot ===&lt;br /&gt;
After the server is restarted, NetBox needs PostgreSQL and Redis to work.&lt;br /&gt;
&lt;br /&gt;
* If PostgreSQL is down, we don&#039;t have any message on the web UI, it serves directly a 500 error code&lt;br /&gt;
* If PostgreSQL up, Redis down, an explicit error message tells us it can&#039;t connect to Redis&lt;br /&gt;
* When both services are up, site should work again&lt;br /&gt;
&lt;br /&gt;
== Conventions ==&lt;br /&gt;
=== Devices ===&lt;br /&gt;
==== Device role colors ====&lt;br /&gt;
* Network appliances and assimilated (e.g. machines with router role): gray&lt;br /&gt;
* Devices for human to connect to and work from (e.g. shellserver, devserver): purple&lt;br /&gt;
* Devices hosting services (e.g. dbserver, paas-docker): pink&lt;/div&gt;</summary>
		<author><name>Dereckson</name></author>
	</entry>
	<entry>
		<id>https://agora.nasqueron.org/index.php?title=Operations_grimoire/NetBox&amp;diff=2552</id>
		<title>Operations grimoire/NetBox</title>
		<link rel="alternate" type="text/html" href="https://agora.nasqueron.org/index.php?title=Operations_grimoire/NetBox&amp;diff=2552"/>
		<updated>2026-07-05T09:51:09Z</updated>

		<summary type="html">&lt;p&gt;Dereckson: /* Python */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;NetBox is the current source of truth for the network. It&#039;s available at [https://netbox.nasqueron.org NetBox].&lt;br /&gt;
&lt;br /&gt;
== Integration with Salt ==&lt;br /&gt;
Ongoing integration projects are in work to serve NetBox data as part of Salt pillar for configuration as code.&lt;br /&gt;
&lt;br /&gt;
It should serve:&lt;br /&gt;
* /etc/hosts data for Drake network machines&lt;br /&gt;
* the same information available at pillar/nodes/nodes.sls, so we won&#039;t need to maintain that anymore&lt;br /&gt;
&lt;br /&gt;
== Integration with IRC ==&lt;br /&gt;
Export to a database for [[Odderon]] is discussed at [https://devcentral.nasqueron.org/T1868 T1868].&lt;br /&gt;
&lt;br /&gt;
That should allow the following workflow:&lt;br /&gt;
&lt;br /&gt;
    17:13:59 &amp;lt; Dereckson&amp;gt; 172.27.27.6&lt;br /&gt;
    17:14:00 &amp;lt; Odderon&amp;gt; (Dereckson): 172.27.27.6/28 docker-001.nasqueron.org / Decommissioned address for docker-001.nasqueron.org / Drake [deprecated]&lt;br /&gt;
&lt;br /&gt;
Source code of the translation code is available at https://devcentral.nasqueron.org/source/netbox-darkbot-db/&lt;br /&gt;
&lt;br /&gt;
== Backup ==&lt;br /&gt;
To backup the PostgreSQL database:&lt;br /&gt;
&lt;br /&gt;
    sudo -u postgres pg_dump netbox | gzip &amp;gt; netbox-$(date +&amp;quot;%Y-%m-%d&amp;quot;).gz&lt;br /&gt;
&lt;br /&gt;
Database is currently hosted on WindRiver, not on DB-A, even if a user exists there and an outdated copy exists.&lt;br /&gt;
&lt;br /&gt;
== Upgrade ==&lt;br /&gt;
=== NetBox ===&lt;br /&gt;
To upgrade NetBox:&lt;br /&gt;
# Backup database on WindRiver&lt;br /&gt;
# Install the new version&lt;br /&gt;
# Copy configuration&lt;br /&gt;
# Update Python dependencies&lt;br /&gt;
# Shutdown the service: &amp;lt;code&amp;gt;service netbox stop&amp;lt;/code&amp;gt; or if pid is wrong &amp;lt;code&amp;gt;killall netbox&amp;lt;/code&amp;gt;&lt;br /&gt;
# Symlink the directory in /srv/netbox&lt;br /&gt;
# Run the database migrations and regenerate static resources, etc. as documented in upgrade.sh&lt;br /&gt;
# Start the service&lt;br /&gt;
&lt;br /&gt;
An example for upgrade to 3.7.0:&lt;br /&gt;
&lt;br /&gt;
    sudo -u postgres pg_dump netbox | gzip &amp;gt; netbox-$(date +&amp;quot;%Y-%m-%d&amp;quot;).gz&lt;br /&gt;
    cd /srv/netbox&lt;br /&gt;
    wget https://github.com/netbox-community/netbox/archive/refs/tags/v3.7.0.tar.gz&lt;br /&gt;
    tar xzf v3.7.0.tar.gz&lt;br /&gt;
    cp /srv/netbox/netbox/netbox/netbox/configuration.py netbox-3.7.0/netbox/netbox/&lt;br /&gt;
    source venv/bin/activate&lt;br /&gt;
    pip install -r netbox-3.7.0/requirements.txt&lt;br /&gt;
    killall -u netbox&lt;br /&gt;
    rm netbox&lt;br /&gt;
    ln -s netbox-3.7.0 netbox&lt;br /&gt;
    cd /srv/netbox/netbox&lt;br /&gt;
    mkdocs build&lt;br /&gt;
    cd /srv/netbox/netbox/netbox&lt;br /&gt;
    python3 manage.py migrate&lt;br /&gt;
    python3 manage.py collectstatic&lt;br /&gt;
    python3 manage.py remove_stale_contenttypes&lt;br /&gt;
    python3 manage.py reindex --lazy&lt;br /&gt;
    python3 manage.py clearsessions&lt;br /&gt;
    service netbox start&lt;br /&gt;
&lt;br /&gt;
To track configuration changes, you can use https://github.com/netbox-community/netbox/commits/develop/netbox/netbox/configuration_example.py&lt;br /&gt;
&lt;br /&gt;
If psycopg can&#039;t build, you can build it with &amp;lt;code&amp;gt;pip install &amp;quot;psycopg[c]&amp;quot;&amp;lt;/code&amp;gt;. That requires development headers for PostgreSQL, available on all FreeBSD servers where PostgreSQL is installed ; for a Docker image based on Linux, search for a libpq-dev or libpq-devel package for that purpose.&lt;br /&gt;
&lt;br /&gt;
Documentation needs to be generated before collectstatic. If not, run again the collectstatic command to copy docs from project-static to static directory.&lt;br /&gt;
&lt;br /&gt;
=== Python ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;This procedure only applies when we do major interpreter change (e.g. Python 3.11 to 3.12) at OS level.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
To recreate the virtual environment with a new Python interpreter, recreate as root an empty venv directory:&lt;br /&gt;
&lt;br /&gt;
    rm -rf /srv/netbox/venv&lt;br /&gt;
    mkdir /srv/netbox/venv&lt;br /&gt;
    chown netbox:netbox /srv/netbox/venv&lt;br /&gt;
&lt;br /&gt;
Then, as netbox user, recreate it:&lt;br /&gt;
&lt;br /&gt;
    python3 -m venv /srv/netbox/venv&lt;br /&gt;
    source /srv/netbox/venv/bin/activate&lt;br /&gt;
    pip install --upgrade pip&lt;br /&gt;
    pip install -r /srv/netbox/netbox/requirements.txt&lt;br /&gt;
&lt;br /&gt;
== Troubleshoot ==&lt;br /&gt;
=== Grafana ===&lt;br /&gt;
&lt;br /&gt;
Use [https://grafana.nasqueron.org/d/O6v4rMpizda/netbox?orgId=1&amp;amp;refresh=10s Grafana dashboard] to check statistics.&lt;br /&gt;
&lt;br /&gt;
As of 2024-08-04, all the rates are erroneous and (a lot) over-evaluated.&lt;br /&gt;
&lt;br /&gt;
=== 500 after server reboot ===&lt;br /&gt;
After the server is restarted, NetBox needs PostgreSQL and Redis to work.&lt;br /&gt;
&lt;br /&gt;
* If PostgreSQL is down, we don&#039;t have any message on the web UI, it serves directly a 500 error code&lt;br /&gt;
* If PostgreSQL up, Redis down, an explicit error message tells us it can&#039;t connect to Redis&lt;br /&gt;
* When both services are up, site should work again&lt;br /&gt;
&lt;br /&gt;
== Conventions ==&lt;br /&gt;
=== Devices ===&lt;br /&gt;
==== Device role colors ====&lt;br /&gt;
* Network appliances and assimilated (e.g. machines with router role): gray&lt;br /&gt;
* Devices for human to connect to and work from (e.g. shellserver, devserver): purple&lt;br /&gt;
* Devices hosting services (e.g. dbserver, paas-docker): pink&lt;/div&gt;</summary>
		<author><name>Dereckson</name></author>
	</entry>
	<entry>
		<id>https://agora.nasqueron.org/index.php?title=Operations_grimoire/NetBox&amp;diff=2551</id>
		<title>Operations grimoire/NetBox</title>
		<link rel="alternate" type="text/html" href="https://agora.nasqueron.org/index.php?title=Operations_grimoire/NetBox&amp;diff=2551"/>
		<updated>2026-07-05T09:50:28Z</updated>

		<summary type="html">&lt;p&gt;Dereckson: /* Upgrade */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;NetBox is the current source of truth for the network. It&#039;s available at [https://netbox.nasqueron.org NetBox].&lt;br /&gt;
&lt;br /&gt;
== Integration with Salt ==&lt;br /&gt;
Ongoing integration projects are in work to serve NetBox data as part of Salt pillar for configuration as code.&lt;br /&gt;
&lt;br /&gt;
It should serve:&lt;br /&gt;
* /etc/hosts data for Drake network machines&lt;br /&gt;
* the same information available at pillar/nodes/nodes.sls, so we won&#039;t need to maintain that anymore&lt;br /&gt;
&lt;br /&gt;
== Integration with IRC ==&lt;br /&gt;
Export to a database for [[Odderon]] is discussed at [https://devcentral.nasqueron.org/T1868 T1868].&lt;br /&gt;
&lt;br /&gt;
That should allow the following workflow:&lt;br /&gt;
&lt;br /&gt;
    17:13:59 &amp;lt; Dereckson&amp;gt; 172.27.27.6&lt;br /&gt;
    17:14:00 &amp;lt; Odderon&amp;gt; (Dereckson): 172.27.27.6/28 docker-001.nasqueron.org / Decommissioned address for docker-001.nasqueron.org / Drake [deprecated]&lt;br /&gt;
&lt;br /&gt;
Source code of the translation code is available at https://devcentral.nasqueron.org/source/netbox-darkbot-db/&lt;br /&gt;
&lt;br /&gt;
== Backup ==&lt;br /&gt;
To backup the PostgreSQL database:&lt;br /&gt;
&lt;br /&gt;
    sudo -u postgres pg_dump netbox | gzip &amp;gt; netbox-$(date +&amp;quot;%Y-%m-%d&amp;quot;).gz&lt;br /&gt;
&lt;br /&gt;
Database is currently hosted on WindRiver, not on DB-A, even if a user exists there and an outdated copy exists.&lt;br /&gt;
&lt;br /&gt;
== Upgrade ==&lt;br /&gt;
=== NetBox ===&lt;br /&gt;
To upgrade NetBox:&lt;br /&gt;
# Backup database on WindRiver&lt;br /&gt;
# Install the new version&lt;br /&gt;
# Copy configuration&lt;br /&gt;
# Update Python dependencies&lt;br /&gt;
# Shutdown the service: &amp;lt;code&amp;gt;service netbox stop&amp;lt;/code&amp;gt; or if pid is wrong &amp;lt;code&amp;gt;killall netbox&amp;lt;/code&amp;gt;&lt;br /&gt;
# Symlink the directory in /srv/netbox&lt;br /&gt;
# Run the database migrations and regenerate static resources, etc. as documented in upgrade.sh&lt;br /&gt;
# Start the service&lt;br /&gt;
&lt;br /&gt;
An example for upgrade to 3.7.0:&lt;br /&gt;
&lt;br /&gt;
    sudo -u postgres pg_dump netbox | gzip &amp;gt; netbox-$(date +&amp;quot;%Y-%m-%d&amp;quot;).gz&lt;br /&gt;
    cd /srv/netbox&lt;br /&gt;
    wget https://github.com/netbox-community/netbox/archive/refs/tags/v3.7.0.tar.gz&lt;br /&gt;
    tar xzf v3.7.0.tar.gz&lt;br /&gt;
    cp /srv/netbox/netbox/netbox/netbox/configuration.py netbox-3.7.0/netbox/netbox/&lt;br /&gt;
    source venv/bin/activate&lt;br /&gt;
    pip install -r netbox-3.7.0/requirements.txt&lt;br /&gt;
    killall -u netbox&lt;br /&gt;
    rm netbox&lt;br /&gt;
    ln -s netbox-3.7.0 netbox&lt;br /&gt;
    cd /srv/netbox/netbox&lt;br /&gt;
    mkdocs build&lt;br /&gt;
    cd /srv/netbox/netbox/netbox&lt;br /&gt;
    python3 manage.py migrate&lt;br /&gt;
    python3 manage.py collectstatic&lt;br /&gt;
    python3 manage.py remove_stale_contenttypes&lt;br /&gt;
    python3 manage.py reindex --lazy&lt;br /&gt;
    python3 manage.py clearsessions&lt;br /&gt;
    service netbox start&lt;br /&gt;
&lt;br /&gt;
To track configuration changes, you can use https://github.com/netbox-community/netbox/commits/develop/netbox/netbox/configuration_example.py&lt;br /&gt;
&lt;br /&gt;
If psycopg can&#039;t build, you can build it with &amp;lt;code&amp;gt;pip install &amp;quot;psycopg[c]&amp;quot;&amp;lt;/code&amp;gt;. That requires development headers for PostgreSQL, available on all FreeBSD servers where PostgreSQL is installed ; for a Docker image based on Linux, search for a libpq-dev or libpq-devel package for that purpose.&lt;br /&gt;
&lt;br /&gt;
Documentation needs to be generated before collectstatic. If not, run again the collectstatic command to copy docs from project-static to static directory.&lt;br /&gt;
&lt;br /&gt;
=== Python ===&lt;br /&gt;
&lt;br /&gt;
To recreate the virtual environment with a new Python interpreter, recreate as root an empty venv directory:&lt;br /&gt;
&lt;br /&gt;
    rm -rf /srv/netbox/venv&lt;br /&gt;
    mkdir /srv/netbox/venv&lt;br /&gt;
    chown netbox:netbox /srv/netbox/venv&lt;br /&gt;
&lt;br /&gt;
Then, as netbox user, recreate it:&lt;br /&gt;
&lt;br /&gt;
    python3 -m venv /srv/netbox/venv&lt;br /&gt;
    source /srv/netbox/venv/bin/activate&lt;br /&gt;
    pip install --upgrade pip&lt;br /&gt;
    pip install -r /srv/netbox/netbox/requirements.txt&lt;br /&gt;
&lt;br /&gt;
== Troubleshoot ==&lt;br /&gt;
=== Grafana ===&lt;br /&gt;
&lt;br /&gt;
Use [https://grafana.nasqueron.org/d/O6v4rMpizda/netbox?orgId=1&amp;amp;refresh=10s Grafana dashboard] to check statistics.&lt;br /&gt;
&lt;br /&gt;
As of 2024-08-04, all the rates are erroneous and (a lot) over-evaluated.&lt;br /&gt;
&lt;br /&gt;
=== 500 after server reboot ===&lt;br /&gt;
After the server is restarted, NetBox needs PostgreSQL and Redis to work.&lt;br /&gt;
&lt;br /&gt;
* If PostgreSQL is down, we don&#039;t have any message on the web UI, it serves directly a 500 error code&lt;br /&gt;
* If PostgreSQL up, Redis down, an explicit error message tells us it can&#039;t connect to Redis&lt;br /&gt;
* When both services are up, site should work again&lt;br /&gt;
&lt;br /&gt;
== Conventions ==&lt;br /&gt;
=== Devices ===&lt;br /&gt;
==== Device role colors ====&lt;br /&gt;
* Network appliances and assimilated (e.g. machines with router role): gray&lt;br /&gt;
* Devices for human to connect to and work from (e.g. shellserver, devserver): purple&lt;br /&gt;
* Devices hosting services (e.g. dbserver, paas-docker): pink&lt;/div&gt;</summary>
		<author><name>Dereckson</name></author>
	</entry>
	<entry>
		<id>https://agora.nasqueron.org/index.php?title=WindRiver&amp;diff=2550</id>
		<title>WindRiver</title>
		<link rel="alternate" type="text/html" href="https://agora.nasqueron.org/index.php?title=WindRiver&amp;diff=2550"/>
		<updated>2026-07-05T09:34:21Z</updated>

		<summary type="html">&lt;p&gt;Dereckson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;WindRiver is an FreeBSD 15 bare metal server for Nasqueron general-purpose development.&lt;br /&gt;
&lt;br /&gt;
It supersedes [[Ysul]].&lt;br /&gt;
&lt;br /&gt;
Upgrade is planned in September 2027, per [[Operations grimoire/Servers lifecycle]].&lt;br /&gt;
&lt;br /&gt;
Documentation: [[Devserver reference]]&lt;br /&gt;
&lt;br /&gt;
== Basic information ==&lt;br /&gt;
* &#039;&#039;&#039;IP:&#039;&#039;&#039;&lt;br /&gt;
** 195.154.30.15 &amp;lt;strike&amp;gt;51.159.17.168 since 2023-06-14. Previously 51.159.18.59.&amp;lt;/strike&amp;gt;&lt;br /&gt;
** 2a02:578:4f0d:0:30d0:7b22:6cde:a52e (native, still to migrate)&lt;br /&gt;
** 2001:bc8:6005:5:aa1e:84ff:fef3:5d9c (future through HE)&lt;br /&gt;
* &#039;&#039;&#039;Hostname:&#039;&#039;&#039; windriver.nasqueron.org&lt;br /&gt;
* &#039;&#039;&#039;Homepage:&#039;&#039;&#039; https://windriver.nasqueron.org/&lt;br /&gt;
* &#039;&#039;&#039;Configuration:&#039;&#039;&#039; &amp;lt;strike&amp;gt;64 Gb RAM, Xeon E3 1240 V6, 2x 500 GB SSD (&amp;quot;Pro-6-S&amp;quot;)&amp;lt;/strike&amp;gt; 96 Gb. RAM, Xeon E5-1650 v3, 3x 500 GB SSD (&amp;quot;Pro-4-L&amp;quot;)&lt;br /&gt;
* &#039;&#039;&#039;ISP:&#039;&#039;&#039; [http://www.online.net Online] (FR)&lt;br /&gt;
* &#039;&#039;&#039;Network:&#039;&#039;&#039; Illiad (FR)&lt;br /&gt;
* &#039;&#039;&#039;Policy:&#039;&#039;&#039; Access for any Nasqueron project and for infrastructure operations task.&lt;br /&gt;
* &#039;&#039;&#039;Started:&#039;&#039;&#039; 2019-11-21&lt;br /&gt;
&lt;br /&gt;
== Ports ==&lt;br /&gt;
&lt;br /&gt;
Ports for services managed automatically through Salt are available on {{Ops file|PORTS}}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Reserved ports - IRC server range&lt;br /&gt;
|-&lt;br /&gt;
! Port !! User account !! Description&lt;br /&gt;
|-&lt;br /&gt;
| 6901 || dereckson || irssi proxy&lt;br /&gt;
|-&lt;br /&gt;
| 6902 || dereckson || irssi proxy&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Troubleshoot ==&lt;br /&gt;
&lt;br /&gt;
=== To check after reboot ===&lt;br /&gt;
&lt;br /&gt;
* Network&lt;br /&gt;
** IPv4 - ICANN&lt;br /&gt;
** IPv6 - main + viperserv alias&lt;br /&gt;
** IPv6 - can we reach something with IPv6&lt;br /&gt;
** IPv4 - Drake: tunnel + route + ping any server&lt;br /&gt;
* Services&lt;br /&gt;
** Alkane HTTP server&lt;br /&gt;
** API exec HTTP server&lt;br /&gt;
** Bitlbee&lt;br /&gt;
** Eggdrops: Dæghrefn + Wearg&lt;br /&gt;
** Grafana&lt;br /&gt;
** MariaDB&lt;br /&gt;
** NetBox&lt;br /&gt;
** nginx&lt;br /&gt;
** Node exporter for Prometheus&lt;br /&gt;
** oidentd&lt;br /&gt;
** php-fpm&lt;br /&gt;
** PostgreSQL&lt;br /&gt;
** Prometheus&lt;br /&gt;
** Redis&lt;br /&gt;
** Salt minion&lt;br /&gt;
** SSH server&lt;br /&gt;
* Vault connectivity&lt;/div&gt;</summary>
		<author><name>Dereckson</name></author>
	</entry>
	<entry>
		<id>https://agora.nasqueron.org/index.php?title=WindRiver&amp;diff=2549</id>
		<title>WindRiver</title>
		<link rel="alternate" type="text/html" href="https://agora.nasqueron.org/index.php?title=WindRiver&amp;diff=2549"/>
		<updated>2026-07-05T09:34:13Z</updated>

		<summary type="html">&lt;p&gt;Dereckson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;WindRiver is an FreeBSD 14 bare metal server for Nasqueron general-purpose development.&lt;br /&gt;
&lt;br /&gt;
It supersedes [[Ysul]].&lt;br /&gt;
&lt;br /&gt;
Upgrade is planned in September 2027, per [[Operations grimoire/Servers lifecycle]].&lt;br /&gt;
&lt;br /&gt;
Documentation: [[Devserver reference]]&lt;br /&gt;
&lt;br /&gt;
== Basic information ==&lt;br /&gt;
* &#039;&#039;&#039;IP:&#039;&#039;&#039;&lt;br /&gt;
** 195.154.30.15 &amp;lt;strike&amp;gt;51.159.17.168 since 2023-06-14. Previously 51.159.18.59.&amp;lt;/strike&amp;gt;&lt;br /&gt;
** 2a02:578:4f0d:0:30d0:7b22:6cde:a52e (native, still to migrate)&lt;br /&gt;
** 2001:bc8:6005:5:aa1e:84ff:fef3:5d9c (future through HE)&lt;br /&gt;
* &#039;&#039;&#039;Hostname:&#039;&#039;&#039; windriver.nasqueron.org&lt;br /&gt;
* &#039;&#039;&#039;Homepage:&#039;&#039;&#039; https://windriver.nasqueron.org/&lt;br /&gt;
* &#039;&#039;&#039;Configuration:&#039;&#039;&#039; &amp;lt;strike&amp;gt;64 Gb RAM, Xeon E3 1240 V6, 2x 500 GB SSD (&amp;quot;Pro-6-S&amp;quot;)&amp;lt;/strike&amp;gt; 96 Gb. RAM, Xeon E5-1650 v3, 3x 500 GB SSD (&amp;quot;Pro-4-L&amp;quot;)&lt;br /&gt;
* &#039;&#039;&#039;ISP:&#039;&#039;&#039; [http://www.online.net Online] (FR)&lt;br /&gt;
* &#039;&#039;&#039;Network:&#039;&#039;&#039; Illiad (FR)&lt;br /&gt;
* &#039;&#039;&#039;Policy:&#039;&#039;&#039; Access for any Nasqueron project and for infrastructure operations task.&lt;br /&gt;
* &#039;&#039;&#039;Started:&#039;&#039;&#039; 2019-11-21&lt;br /&gt;
&lt;br /&gt;
== Ports ==&lt;br /&gt;
&lt;br /&gt;
Ports for services managed automatically through Salt are available on {{Ops file|PORTS}}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Reserved ports - IRC server range&lt;br /&gt;
|-&lt;br /&gt;
! Port !! User account !! Description&lt;br /&gt;
|-&lt;br /&gt;
| 6901 || dereckson || irssi proxy&lt;br /&gt;
|-&lt;br /&gt;
| 6902 || dereckson || irssi proxy&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Troubleshoot ==&lt;br /&gt;
&lt;br /&gt;
=== To check after reboot ===&lt;br /&gt;
&lt;br /&gt;
* Network&lt;br /&gt;
** IPv4 - ICANN&lt;br /&gt;
** IPv6 - main + viperserv alias&lt;br /&gt;
** IPv6 - can we reach something with IPv6&lt;br /&gt;
** IPv4 - Drake: tunnel + route + ping any server&lt;br /&gt;
* Services&lt;br /&gt;
** Alkane HTTP server&lt;br /&gt;
** API exec HTTP server&lt;br /&gt;
** Bitlbee&lt;br /&gt;
** Eggdrops: Dæghrefn + Wearg&lt;br /&gt;
** Grafana&lt;br /&gt;
** MariaDB&lt;br /&gt;
** NetBox&lt;br /&gt;
** nginx&lt;br /&gt;
** Node exporter for Prometheus&lt;br /&gt;
** oidentd&lt;br /&gt;
** php-fpm&lt;br /&gt;
** PostgreSQL&lt;br /&gt;
** Prometheus&lt;br /&gt;
** Redis&lt;br /&gt;
** Salt minion&lt;br /&gt;
** SSH server&lt;br /&gt;
* Vault connectivity&lt;/div&gt;</summary>
		<author><name>Dereckson</name></author>
	</entry>
	<entry>
		<id>https://agora.nasqueron.org/index.php?title=Operations_grimoire/Servers_lifecycle&amp;diff=2548</id>
		<title>Operations grimoire/Servers lifecycle</title>
		<link rel="alternate" type="text/html" href="https://agora.nasqueron.org/index.php?title=Operations_grimoire/Servers_lifecycle&amp;diff=2548"/>
		<updated>2026-07-05T09:33:29Z</updated>

		<summary type="html">&lt;p&gt;Dereckson: Created page with &amp;quot;This resource tracks the servers lifecycle, when we&amp;#039;ve to plan rollout and decom.  == Contracts ==  {| class=&amp;quot;wikitable&amp;quot; |+ Servers with engagement contract |- ! Server name !! Provider !! Start date !! End date !! Conditions !! Current decision |- | WindRiver || Scaleway || 2024-09-12 || 2027-09-12 || -20% || Upgrade to another server with faster CPU |}&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This resource tracks the servers lifecycle, when we&#039;ve to plan rollout and decom.&lt;br /&gt;
&lt;br /&gt;
== Contracts ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Servers with engagement contract&lt;br /&gt;
|-&lt;br /&gt;
! Server name !! Provider !! Start date !! End date !! Conditions !! Current decision&lt;br /&gt;
|-&lt;br /&gt;
| [[WindRiver]] || Scaleway || 2024-09-12 || 2027-09-12 || -20% || Upgrade to another server with faster CPU&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Dereckson</name></author>
	</entry>
	<entry>
		<id>https://agora.nasqueron.org/index.php?title=Operations_grimoire&amp;diff=2547</id>
		<title>Operations grimoire</title>
		<link rel="alternate" type="text/html" href="https://agora.nasqueron.org/index.php?title=Operations_grimoire&amp;diff=2547"/>
		<updated>2026-07-05T09:30:44Z</updated>

		<summary type="html">&lt;p&gt;Dereckson: /* Infrastructure */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:Nasqueron Operations Grimoire.jpg|thumb|320px|right|The Nasqueron operations grimoire tries to document the more arcane aspects of our complex infrastructure.]]&lt;br /&gt;
&lt;br /&gt;
Welcome to the Nasqueron operations grimoire (NOG).&lt;br /&gt;
&lt;br /&gt;
This grimoire is a reference about our infrastructure and services hosted with procedures we follow to build, maintain and deploy.&lt;br /&gt;
&lt;br /&gt;
Our infrastructure is open, mainly documented in {{repo|operations}} repository, and we actively encourage contributions from the community.&lt;br /&gt;
&lt;br /&gt;
== Infrastructure ==&lt;br /&gt;
* [[/Environments]]&lt;br /&gt;
* [[/Kubernetes]]&lt;br /&gt;
* [[/Docker engine]]&lt;br /&gt;
* [[/Salt]]&lt;br /&gt;
* [[/Servers lifecycle]]&lt;br /&gt;
&lt;br /&gt;
=== OS-specific ===&lt;br /&gt;
;By OS&lt;br /&gt;
* [[/FreeBSD]]&lt;br /&gt;
* [[/RHEL]]&lt;br /&gt;
&lt;br /&gt;
;All OSes&lt;br /&gt;
* [[/NTP]]&lt;br /&gt;
* [[/Packages repository]]&lt;br /&gt;
* [[/Services]]: systemd, runit and rc&lt;br /&gt;
&lt;br /&gt;
=== Storage ===&lt;br /&gt;
* [[/ZFS]]&lt;br /&gt;
&lt;br /&gt;
=== Observability ===&lt;br /&gt;
* [[/Grafana]]&lt;br /&gt;
* [[/Logs]]&lt;br /&gt;
* [[/Prometheus]]&lt;br /&gt;
&lt;br /&gt;
=== Network ===&lt;br /&gt;
* [[/Network]]&lt;br /&gt;
* [[/DNS]]&lt;br /&gt;
* [[/Firewall]]&lt;br /&gt;
* [[/Router]]&lt;br /&gt;
* [[/IPv6]]&lt;br /&gt;
* [https://netbox.nasqueron.org/ NetBox]&lt;br /&gt;
&lt;br /&gt;
== Services ==&lt;br /&gt;
=== Core services ===&lt;br /&gt;
; Messages queues&lt;br /&gt;
* [[/Kafka]]&lt;br /&gt;
* [[/RabbitMQ]]&lt;br /&gt;
&lt;br /&gt;
; Databases&lt;br /&gt;
* [[/MySQL]]&lt;br /&gt;
* [[/PostgreSQL]]&lt;br /&gt;
&lt;br /&gt;
; Ops&lt;br /&gt;
* [[/NetBox]]&lt;br /&gt;
&lt;br /&gt;
=== Identity management ===&lt;br /&gt;
* [[/Login]] (Auth Grove)&lt;br /&gt;
&lt;br /&gt;
=== Collaborative tools ===&lt;br /&gt;
* [[/DevCentral]] (Phabricator)&lt;br /&gt;
* [[/Etherpad]]&lt;br /&gt;
* [[/Mumble]]&lt;br /&gt;
* [[/Mastodon]] (social.nasqueron.org)&lt;br /&gt;
* [[/Openfire]] (XMPP)&lt;br /&gt;
&lt;br /&gt;
=== IRC bots ===&lt;br /&gt;
* [[/Dæghrefn]] (eggdrop)&lt;br /&gt;
* [[/Odderon]] (darkbot)&lt;br /&gt;
&lt;br /&gt;
=== Mail ===&lt;br /&gt;
* [[/Mail]]&lt;br /&gt;
* [[/Mail/DKIM]]&lt;br /&gt;
* [[/Mail/Sympa]]&lt;br /&gt;
&lt;br /&gt;
=== Web ===&lt;br /&gt;
; Common documentation for all webserver roles&lt;br /&gt;
* [[/Web/Headers]]&lt;br /&gt;
&lt;br /&gt;
; Where to host?&lt;br /&gt;
* [[/Docker engine]] for Docker containers front-end&lt;br /&gt;
* [[/Alkane]] for PHP and static sites&lt;br /&gt;
&lt;br /&gt;
; SaaS for common applications&lt;br /&gt;
* [[MediaWiki SaaS]]&lt;br /&gt;
* [[/WordPress]]&lt;br /&gt;
&lt;br /&gt;
; Other sites&lt;br /&gt;
* [[/Sites on Eglide]]&lt;br /&gt;
* [[/Sites on Ysul]] (currently migrating to Alkane)&lt;br /&gt;
&lt;br /&gt;
; Services for web applications&lt;br /&gt;
* [[/Anubis]] if you need to protect from LLM scraping traffic&lt;br /&gt;
* [[/Orbeon]] if you&#039;re in need of a form&lt;br /&gt;
&lt;br /&gt;
=== CI/CD ===&lt;br /&gt;
* [[/Broker]]&lt;br /&gt;
* [[/Docker registry]]&lt;br /&gt;
* [[/Jenkins]]&lt;br /&gt;
* [[/Notifications center]]&lt;br /&gt;
* [[/Sentry]]&lt;br /&gt;
* [[/Vault]]&lt;br /&gt;
&lt;br /&gt;
=== Shellserver ===&lt;br /&gt;
* [[/Eglide/Vault]]&lt;br /&gt;
&lt;br /&gt;
== Services configuration ==&lt;br /&gt;
&#039;&#039;This section contains general information not related to a specific service.&#039;&#039;&lt;br /&gt;
* [[/TLS certificates]] (Let&#039;s encrypt / letsencrypt)&lt;br /&gt;
&lt;br /&gt;
== Checklists ==&lt;br /&gt;
=== SSH ===&lt;br /&gt;
* [[/Recommended SSH configuration]]&lt;br /&gt;
&lt;br /&gt;
=== Infrastructure ===&lt;br /&gt;
* [[/How to add a server to the Nasqueron servers pool]]&lt;br /&gt;
* [[/How to attach a new virtual disk]]&lt;br /&gt;
* [[/Reboot checklist]]&lt;br /&gt;
&lt;br /&gt;
=== Network ===&lt;br /&gt;
* [[/Checklist router post-restart]]&lt;br /&gt;
&lt;br /&gt;
=== Docker ===&lt;br /&gt;
* [[/Restart a Docker engine]]&lt;br /&gt;
* [[/Dwellers to DevCentral]]&lt;br /&gt;
* [[/Git operations in production containers]]&lt;br /&gt;
* [[/Add a service to Docker PaaS]]&lt;br /&gt;
* [[/Docker Hub]]&lt;br /&gt;
&lt;br /&gt;
=== Salt ===&lt;br /&gt;
* [[/Operations repository]]&lt;br /&gt;
* [[/Deploy with Salt]]&lt;br /&gt;
* [[/Create and revoke user accounts on Salt servers]]&lt;br /&gt;
* [[/Provision user homefiles]]&lt;br /&gt;
&lt;br /&gt;
=== Terraform / OpenTofu ===&lt;br /&gt;
* [[/Deploy with Terraform]]&lt;br /&gt;
&lt;br /&gt;
== SIG ==&lt;br /&gt;
* [[/Onboarding]]&lt;br /&gt;
&lt;br /&gt;
== Appendices ==&lt;br /&gt;
* [[/Changelog]]&lt;br /&gt;
* [[/Contacts]]&lt;br /&gt;
* [[/Configuration files]]&lt;br /&gt;
* [[/Contribute]]&lt;br /&gt;
* [[/Decom]]&lt;br /&gt;
* [[/Evaluated products]]&lt;br /&gt;
* [[/External services]]&lt;br /&gt;
* [[/Incidents]]&lt;br /&gt;
* [[/Legacy archive]]&lt;br /&gt;
* [[/OID]]&lt;br /&gt;
* [[/Old content report]]&lt;br /&gt;
* [[/Policies]]&lt;br /&gt;
* [[/Who]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Operations grimoire|*]]&lt;br /&gt;
[[Category:Reference]]&lt;/div&gt;</summary>
		<author><name>Dereckson</name></author>
	</entry>
	<entry>
		<id>https://agora.nasqueron.org/index.php?title=User:Dereckson/Arcane_Grove/BlueDrake&amp;diff=2546</id>
		<title>User:Dereckson/Arcane Grove/BlueDrake</title>
		<link rel="alternate" type="text/html" href="https://agora.nasqueron.org/index.php?title=User:Dereckson/Arcane_Grove/BlueDrake&amp;diff=2546"/>
		<updated>2026-06-28T21:49:00Z</updated>

		<summary type="html">&lt;p&gt;Dereckson: /* Components */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;BlueDrake&#039;&#039;&#039; is the name of the hybrid productivity-gaming workstation.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
=== Components ===&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
|+ BlueDrake parts&lt;br /&gt;
|-&lt;br /&gt;
! Category !! Brand !! Model !! Links&lt;br /&gt;
|-&lt;br /&gt;
| Case || Lian Li || [https://lian-li.com/product/lancool-iii/ Lancool III] || [https://drive.google.com/file/d/1kd9ku_raF2uXWeLD7voGfT4ZZ10XOizy/view?usp=sharing 📖]&lt;br /&gt;
|-&lt;br /&gt;
| Motherboard || Asus || [https://rog.asus.com/motherboards/rog-strix/rog-strix-b650e-e-gaming-wifi-model/ ROG Strix B650E-E Gaming WiFi] || [https://rog.asus.com/motherboards/rog-strix/rog-strix-b650e-e-gaming-wifi-model/helpdesk_manual/ 📖] [https://rog.asus.com/motherboards/rog-strix/rog-strix-b650e-e-gaming-wifi-model/helpdesk_download/ 📥]&lt;br /&gt;
|-&lt;br /&gt;
| CPU || AMD || Ryzen 9 7900X || [https://www.amd.com/en/products/cpu/amd-ryzen-9-7900x 📖]&lt;br /&gt;
|-&lt;br /&gt;
| CPU Cooler || Noctua || NH-D15S || [https://noctua.at/en/nh-d15s 📖] [https://noctua.at/en/nh-d15s/manuals 📥]&lt;br /&gt;
|-&lt;br /&gt;
| GPU || Sapphire / AMD || PURE Radeon RX 7700 XT 12GB || [https://www.sapphiretech.com/en/consumer/pure-radeon-rx-7700-xt-12g-gddr6-frostpunk2 📖]&lt;br /&gt;
|-&lt;br /&gt;
| RAM || G.Skill || Trident Z Neo DDR5 96 GB (2×48 GB) || [https://www.gskill.com/product/165/374/1682577390/F5-5600J4040D48GX2-TZ5RK 📖]&lt;br /&gt;
|-&lt;br /&gt;
| Storage || Kingston || Fury Renegade 2 TB NVMe M.2 (×2) || [https://www.kingston.com/en/ssd/gaming/fury-renegade-nvme-pcie-ssd 📖]&lt;br /&gt;
|-&lt;br /&gt;
| PSU || Seasonic || Core GX-750 || [https://seasonic.com/core-gx#specification 📖]&lt;br /&gt;
|-&lt;br /&gt;
| Screen || AOC || C27G1 || [https://aoc.com/be-fr/gaming/products/monitors/c27g1/downloads 📥]&lt;br /&gt;
|-&lt;br /&gt;
| Screen || Alienware || AW3425DWM || [https://dl.dell.com/content/manual56809116-alienware-34-gaming-monitor-aw3425dwm-quick-start-guide.pdf?language=en-us 📖]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; Alienware screen ordered, still to be shipped and installed.&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
=== FreeBSD ===&lt;br /&gt;
Things to check for GPU:&lt;br /&gt;
* Ollama on FreeBSD -&amp;gt; https://www.reddit.com/r/freebsd/comments/1d3hmmz/comment/lqiulx9/ / https://github.com/ollama/ollama/pull/4172 (&amp;lt;code&amp;gt;pkg install go122 cmake vulkan-headers vulkan-loader&amp;lt;/code&amp;gt;)&lt;br /&gt;
* GPU passthrough with bhyve -&amp;gt; https://wiki.freebsd.org/bhyve/pci_passthru&lt;/div&gt;</summary>
		<author><name>Dereckson</name></author>
	</entry>
	<entry>
		<id>https://agora.nasqueron.org/index.php?title=User_talk:Dereckson/Arcane_Grove/BlueDrake&amp;diff=2545</id>
		<title>User talk:Dereckson/Arcane Grove/BlueDrake</title>
		<link rel="alternate" type="text/html" href="https://agora.nasqueron.org/index.php?title=User_talk:Dereckson/Arcane_Grove/BlueDrake&amp;diff=2545"/>
		<updated>2026-06-23T19:28:36Z</updated>

		<summary type="html">&lt;p&gt;Dereckson: Created page with &amp;quot;== Version in YAML to use with LLM ==  &amp;lt;syntaxhighlight lang=&amp;quot;yaml&amp;quot;&amp;gt; components:   - category: Case     brand: Lian Li     model: Lancool III     links:       manual: https://drive.google.com/file/d/1kd9ku_raF2uXWeLD7voGfT4ZZ10XOizy/view?usp=sharing    - category: Motherboard     brand: Asus     model: ROG Strix B650E-E Gaming WiFi     links:       product: https://rog.asus.com/motherboards/rog-strix/rog-strix-b650e-e-gaming-wifi-model/       manual: https://rog.asus.com...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Version in YAML to use with LLM ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;yaml&amp;quot;&amp;gt;&lt;br /&gt;
components:&lt;br /&gt;
  - category: Case&lt;br /&gt;
    brand: Lian Li&lt;br /&gt;
    model: Lancool III&lt;br /&gt;
    links:&lt;br /&gt;
      manual: https://drive.google.com/file/d/1kd9ku_raF2uXWeLD7voGfT4ZZ10XOizy/view?usp=sharing&lt;br /&gt;
&lt;br /&gt;
  - category: Motherboard&lt;br /&gt;
    brand: Asus&lt;br /&gt;
    model: ROG Strix B650E-E Gaming WiFi&lt;br /&gt;
    links:&lt;br /&gt;
      product: https://rog.asus.com/motherboards/rog-strix/rog-strix-b650e-e-gaming-wifi-model/&lt;br /&gt;
      manual: https://rog.asus.com/motherboards/rog-strix/rog-strix-b650e-e-gaming-wifi-model/helpdesk_manual/&lt;br /&gt;
      downloads: https://rog.asus.com/motherboards/rog-strix/rog-strix-b650e-e-gaming-wifi-model/helpdesk_download/&lt;br /&gt;
&lt;br /&gt;
  - category: CPU&lt;br /&gt;
    brand: AMD&lt;br /&gt;
    model: Ryzen 9 7900X&lt;br /&gt;
    links:&lt;br /&gt;
      product: https://www.amd.com/en/products/cpu/amd-ryzen-9-7900x&lt;br /&gt;
&lt;br /&gt;
  - category: CPU Cooler&lt;br /&gt;
    brand: Noctua&lt;br /&gt;
    model: NH-D15S&lt;br /&gt;
    links:&lt;br /&gt;
      product: https://noctua.at/en/nh-d15s&lt;br /&gt;
      manuals: https://noctua.at/en/nh-d15s/manuals&lt;br /&gt;
&lt;br /&gt;
  - category: GPU&lt;br /&gt;
    brand: Sapphire / AMD&lt;br /&gt;
    model: PURE Radeon RX 7700 XT 12GB&lt;br /&gt;
    links:&lt;br /&gt;
      product: https://www.sapphiretech.com/en/consumer/pure-radeon-rx-7700-xt-12g-gddr6-frostpunk2&lt;br /&gt;
&lt;br /&gt;
  - category: RAM&lt;br /&gt;
    brand: G.Skill&lt;br /&gt;
    model: Trident Z Neo DDR5 96 GB (2×48 GB)&lt;br /&gt;
    links:&lt;br /&gt;
      product: https://www.gskill.com/product/165/374/1682577390/F5-5600J4040D48GX2-TZ5RK&lt;br /&gt;
&lt;br /&gt;
  - category: Storage&lt;br /&gt;
    brand: Kingston&lt;br /&gt;
    model: Fury Renegade 2 TB NVMe M.2 (x2)&lt;br /&gt;
    links:&lt;br /&gt;
      product: https://www.kingston.com/en/ssd/gaming/fury-renegade-nvme-pcie-ssd&lt;br /&gt;
&lt;br /&gt;
  - category: PSU&lt;br /&gt;
    brand: Seasonic&lt;br /&gt;
    model: Core GX-750&lt;br /&gt;
    links:&lt;br /&gt;
      product: https://seasonic.com/core-gx#specification&lt;br /&gt;
&lt;br /&gt;
  - category: Screen&lt;br /&gt;
    brand: AOC&lt;br /&gt;
    model: C27G1&lt;br /&gt;
    links:&lt;br /&gt;
      downloads: https://aoc.com/be-fr/gaming/products/monitors/c27g1/downloads&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Dereckson</name></author>
	</entry>
	<entry>
		<id>https://agora.nasqueron.org/index.php?title=Operations_grimoire/Operations_repository&amp;diff=2544</id>
		<title>Operations grimoire/Operations repository</title>
		<link rel="alternate" type="text/html" href="https://agora.nasqueron.org/index.php?title=Operations_grimoire/Operations_repository&amp;diff=2544"/>
		<updated>2026-06-07T11:32:13Z</updated>

		<summary type="html">&lt;p&gt;Dereckson: /* macOS */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Our configuration as code is stores in the operations (rOPS) repository.&lt;br /&gt;
&lt;br /&gt;
== Repository layout ==&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
|+ Content of rOPS&lt;br /&gt;
|-&lt;br /&gt;
! Path !! Description&lt;br /&gt;
|-&lt;br /&gt;
| _modules || Custom execution modules&lt;br /&gt;
|-&lt;br /&gt;
| _states || Custom states modules&lt;br /&gt;
|-&lt;br /&gt;
| _tests || Unit tests for custom modules, scripts, tests for repo&lt;br /&gt;
|-&lt;br /&gt;
| hotfixes || Fixes you need to run to solve a problem on the servers&lt;br /&gt;
|-&lt;br /&gt;
| pillar || Configuration data structures to use in the states&lt;br /&gt;
|-&lt;br /&gt;
| roles || The states to deploy, divided in roles and then in units&lt;br /&gt;
|-&lt;br /&gt;
| utils || Helper scripts to maintain the repository&lt;br /&gt;
|-&lt;br /&gt;
| terraform || OpenTofu / Terraform infrastructure configuration&lt;br /&gt;
|-&lt;br /&gt;
| map.jinja || As we deploy on several OS and distros, mapping of packages names or directories&lt;br /&gt;
|-&lt;br /&gt;
| top.sls || topfile: what we deploy where?&lt;br /&gt;
|-&lt;br /&gt;
| PORTS || Documentation of the ports used in the configuration&lt;br /&gt;
|-&lt;br /&gt;
| UIDs || Documentation of the users used in the configuration&lt;br /&gt;
|-&lt;br /&gt;
| GIDs || Documentation of the groups used in the configuration&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Contributions howto ==&lt;br /&gt;
=== Repository source ===&lt;br /&gt;
You&#039;ll find the Operations repository at https://devcentral.nasqueron.org/source/operations/&lt;br /&gt;
&lt;br /&gt;
If DevCentral isn&#039;t available, a mirror of the repository can be found at https://github.com/nasqueron/operations.&lt;br /&gt;
&lt;br /&gt;
=== Workflow of contributions ===&lt;br /&gt;
We follow the general workflow is described at [[How to contribute code]].&lt;br /&gt;
&lt;br /&gt;
Before committing a change to the main branch, you can test a deployment on a server.&lt;br /&gt;
In that case, merge in main immediately after the deployment as the repository is the source of truth for the server state.&lt;br /&gt;
&lt;br /&gt;
Log what you do on #nasqueron-ops, so it will be included at https://infra.nasqueron.org/servers-log/&lt;br /&gt;
&lt;br /&gt;
=== Code conventions ===&lt;br /&gt;
&#039;&#039;See also: [[Code conventions]].&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Python code: run `black` before committing&lt;br /&gt;
* YAML: indent with two spaces, including list bullets&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;yaml&amp;quot;&amp;gt;&lt;br /&gt;
id:&lt;br /&gt;
  method:&lt;br /&gt;
    - somekey: value&lt;br /&gt;
    - otherkey: value&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Environment setup ==&lt;br /&gt;
&lt;br /&gt;
Use of WindRiver is recommended if you wish to get an environment already installed for your contributions.&lt;br /&gt;
&lt;br /&gt;
=== Everywhere setup ===&lt;br /&gt;
This section cover topics needed both on our development servers or in your laptop.&lt;br /&gt;
&lt;br /&gt;
==== Python dependencies ====&lt;br /&gt;
&lt;br /&gt;
Create a virtual environment, then install dependencies from {{Ops file|requirements.txt}}:&lt;br /&gt;
&lt;br /&gt;
    mkdir -p $HOME/dev/python/ops&lt;br /&gt;
    python3 -m venv $HOME/dev/python/ops&lt;br /&gt;
    source $HOME/dev/python/ops/bin/activate&lt;br /&gt;
    pip install -r requirements.txt&lt;br /&gt;
&lt;br /&gt;
==== Datacube ====&lt;br /&gt;
&lt;br /&gt;
If you&#039;re in the ops group, you&#039;ll need sometimes to deploy from branches. As our deployment server Complector doesn&#039;t have PHP installed (so no arc), you need to exchange branches through our datacube.&lt;br /&gt;
&lt;br /&gt;
On WindRiver:&lt;br /&gt;
&lt;br /&gt;
     git remote add datacube /datacube/git/operations.git&lt;br /&gt;
&lt;br /&gt;
Anywhere else:&lt;br /&gt;
&lt;br /&gt;
     git remote add datacube ssh://windriver.nasqueron.org/datacube/git/operations.git&lt;br /&gt;
&lt;br /&gt;
If you aren&#039;t in the ops groups, and have access to our devserver, you&#039;ll still be able to clone or pull from that directory, but not to write there (ie push branches).&lt;br /&gt;
&lt;br /&gt;
=== Local computer setup ===&lt;br /&gt;
&lt;br /&gt;
This section cover topics NOT needed on our development servers.&lt;br /&gt;
&lt;br /&gt;
==== macOS ====&lt;br /&gt;
&lt;br /&gt;
To run tests properly, install first:&lt;br /&gt;
&lt;br /&gt;
    brew install bats&lt;br /&gt;
    brew install python3.13&lt;br /&gt;
&lt;br /&gt;
You can now setup the virtual environment per everywhere setup instructions.&lt;br /&gt;
&lt;br /&gt;
Salt behaves correctly on macOS, so you can install it safely in the virtual environment:&lt;br /&gt;
&lt;br /&gt;
    pip install salt==3006.25&lt;br /&gt;
&lt;br /&gt;
Check the version on WindRiver or Complector with &amp;lt;code&amp;gt;salt --versions&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Finally, to run the tests, you need a recent version of make, but the BSD make currently shipped, as of Tahoe 26.5, isn&#039;t up-to-date:&lt;br /&gt;
&lt;br /&gt;
    brew install gmake&lt;br /&gt;
    (cd _tests &amp;amp;&amp;amp; gmake)&lt;br /&gt;
&lt;br /&gt;
==== Arcanist ====&lt;br /&gt;
&lt;br /&gt;
To use arc with the operations repository, our collection of patches is needed.&lt;br /&gt;
&lt;br /&gt;
If arcanist isn&#039;t installed through Git repository, best is to do like on devserver role:&lt;br /&gt;
&lt;br /&gt;
    mkdir /opt/phabricator &amp;amp;&amp;amp; cd /opt/phabricator&lt;br /&gt;
    git clone https://github.com/nasqueron/arcanist.git&lt;br /&gt;
    (cd arcanist &amp;amp;&amp;amp; git checkout production)&lt;br /&gt;
    ln -s /opt/phabricator/arcanist/bin/arc /usr/local/bin/&lt;br /&gt;
    git clone https://devcentral.nasqueron.org/source/shellcheck-linter.git&lt;br /&gt;
&lt;br /&gt;
If you&#039;ve already cloned Arcanist repository, switch to our branch production:&lt;br /&gt;
&lt;br /&gt;
    git remote add nasqueron git@github.com:nasqueron/arcanist.git&lt;br /&gt;
    git fetch --all&lt;br /&gt;
    git checkout production&lt;br /&gt;
&lt;br /&gt;
As of August 2024, there is no plan to make that repository available on DevCentral.&lt;br /&gt;
&lt;br /&gt;
You&#039;ll also need shellcheck library-linter library, normally at the same level than your arcanist repository.&lt;br /&gt;
&lt;br /&gt;
==== IDE configuration ====&lt;br /&gt;
[[File:PyCharm-TemplateLanguages.png|thumb|right|Screenshot of correctly configured template languages]]&lt;br /&gt;
The states .sls file are Jinja2 templates producing YAML files, or &amp;quot;jinja2+yaml&amp;quot;. If this case can&#039;t be handled by your IDE, it works best to use YAML syntax highlighting.&lt;br /&gt;
&lt;br /&gt;
If you use PyCharm or IntelliJ IDEA Ultimate, you can configure this scheme:&lt;br /&gt;
&lt;br /&gt;
* Allow YAML files to be Jinja2 templates&lt;br /&gt;
** Go to Settings &amp;gt; Languages &amp;amp; Frameworks &amp;gt; Template Languages&lt;br /&gt;
** Select Jinja2 as template language&lt;br /&gt;
** Add YAML in the list&lt;br /&gt;
* Open SLS as YAML&lt;br /&gt;
&lt;br /&gt;
== Linting ==&lt;br /&gt;
&lt;br /&gt;
=== pre-commit ===&lt;br /&gt;
You can use &#039;&#039;&#039;pre-commit&#039;&#039;&#039; you can install with &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; to get a hook running Python code to lint the repository before a commit.&lt;br /&gt;
&lt;br /&gt;
Beware if you use &amp;lt;code&amp;gt;arc diff&amp;lt;/code&amp;gt; without a commit first: your message will be lost if pre-commit raises an error, always use &amp;lt;code&amp;gt;git commit&amp;lt;/code&amp;gt; first.&lt;br /&gt;
&lt;br /&gt;
On FreeBSD, there is an issue to build with clang 16+ the ruamel yaml clib library. You can build the FreeBSD port devel/py-ruamel.yaml.clib and copy the .whl to a stable path, then install it in your virtual environment.&lt;br /&gt;
&lt;br /&gt;
On WindRiver, the .whl is available in /opt/python/py311, so you can:&lt;br /&gt;
&lt;br /&gt;
    $ python3 -m venv /path/to/your/virtualenv&lt;br /&gt;
    $ source /path/to/your/virtualenv/bin/activate&lt;br /&gt;
    $ pip install /opt/python/py311/ruamel.yaml.clib-0.2.8-cp311-cp311-freebsd_14_0_release_p3_amd64.whl&lt;br /&gt;
    $ pip install pre-commit&lt;br /&gt;
    $ make&lt;br /&gt;
    pre-commit install&lt;br /&gt;
    pre-commit installed at .git/hooks/pre-commit&lt;br /&gt;
    $ rehash&lt;br /&gt;
    $ pre-commit&lt;br /&gt;
&lt;br /&gt;
== Refactoring ==&lt;br /&gt;
&lt;br /&gt;
=== Rename a lot of files ===&lt;br /&gt;
&lt;br /&gt;
To move a directory and rename the &#039;&#039;Source file&#039;&#039; headers:&lt;br /&gt;
&lt;br /&gt;
    git mv roles/webserver-legacy/nginx/files roles/webserver-alkane/nginx/&lt;br /&gt;
    cd roles/webserver-alkane/nginx/&lt;br /&gt;
    find . -type f -name &#039;*.conf&#039; | xargs gsed -i s/webserver-legacy/webserver-alkane/g&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
* [[/FAQ]] - Frequently asked questions about the Operations repository&lt;br /&gt;
* [[How to contribute code]]&lt;br /&gt;
* [[Devserver reference]]&lt;/div&gt;</summary>
		<author><name>Dereckson</name></author>
	</entry>
	<entry>
		<id>https://agora.nasqueron.org/index.php?title=Operations_grimoire/Operations_repository&amp;diff=2543</id>
		<title>Operations grimoire/Operations repository</title>
		<link rel="alternate" type="text/html" href="https://agora.nasqueron.org/index.php?title=Operations_grimoire/Operations_repository&amp;diff=2543"/>
		<updated>2026-06-07T11:31:03Z</updated>

		<summary type="html">&lt;p&gt;Dereckson: /* Local computer setup */ Notes for macOS&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Our configuration as code is stores in the operations (rOPS) repository.&lt;br /&gt;
&lt;br /&gt;
== Repository layout ==&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
|+ Content of rOPS&lt;br /&gt;
|-&lt;br /&gt;
! Path !! Description&lt;br /&gt;
|-&lt;br /&gt;
| _modules || Custom execution modules&lt;br /&gt;
|-&lt;br /&gt;
| _states || Custom states modules&lt;br /&gt;
|-&lt;br /&gt;
| _tests || Unit tests for custom modules, scripts, tests for repo&lt;br /&gt;
|-&lt;br /&gt;
| hotfixes || Fixes you need to run to solve a problem on the servers&lt;br /&gt;
|-&lt;br /&gt;
| pillar || Configuration data structures to use in the states&lt;br /&gt;
|-&lt;br /&gt;
| roles || The states to deploy, divided in roles and then in units&lt;br /&gt;
|-&lt;br /&gt;
| utils || Helper scripts to maintain the repository&lt;br /&gt;
|-&lt;br /&gt;
| terraform || OpenTofu / Terraform infrastructure configuration&lt;br /&gt;
|-&lt;br /&gt;
| map.jinja || As we deploy on several OS and distros, mapping of packages names or directories&lt;br /&gt;
|-&lt;br /&gt;
| top.sls || topfile: what we deploy where?&lt;br /&gt;
|-&lt;br /&gt;
| PORTS || Documentation of the ports used in the configuration&lt;br /&gt;
|-&lt;br /&gt;
| UIDs || Documentation of the users used in the configuration&lt;br /&gt;
|-&lt;br /&gt;
| GIDs || Documentation of the groups used in the configuration&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Contributions howto ==&lt;br /&gt;
=== Repository source ===&lt;br /&gt;
You&#039;ll find the Operations repository at https://devcentral.nasqueron.org/source/operations/&lt;br /&gt;
&lt;br /&gt;
If DevCentral isn&#039;t available, a mirror of the repository can be found at https://github.com/nasqueron/operations.&lt;br /&gt;
&lt;br /&gt;
=== Workflow of contributions ===&lt;br /&gt;
We follow the general workflow is described at [[How to contribute code]].&lt;br /&gt;
&lt;br /&gt;
Before committing a change to the main branch, you can test a deployment on a server.&lt;br /&gt;
In that case, merge in main immediately after the deployment as the repository is the source of truth for the server state.&lt;br /&gt;
&lt;br /&gt;
Log what you do on #nasqueron-ops, so it will be included at https://infra.nasqueron.org/servers-log/&lt;br /&gt;
&lt;br /&gt;
=== Code conventions ===&lt;br /&gt;
&#039;&#039;See also: [[Code conventions]].&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Python code: run `black` before committing&lt;br /&gt;
* YAML: indent with two spaces, including list bullets&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;yaml&amp;quot;&amp;gt;&lt;br /&gt;
id:&lt;br /&gt;
  method:&lt;br /&gt;
    - somekey: value&lt;br /&gt;
    - otherkey: value&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Environment setup ==&lt;br /&gt;
&lt;br /&gt;
Use of WindRiver is recommended if you wish to get an environment already installed for your contributions.&lt;br /&gt;
&lt;br /&gt;
=== Everywhere setup ===&lt;br /&gt;
This section cover topics needed both on our development servers or in your laptop.&lt;br /&gt;
&lt;br /&gt;
==== Python dependencies ====&lt;br /&gt;
&lt;br /&gt;
Create a virtual environment, then install dependencies from {{Ops file|requirements.txt}}:&lt;br /&gt;
&lt;br /&gt;
    mkdir -p $HOME/dev/python/ops&lt;br /&gt;
    python3 -m venv $HOME/dev/python/ops&lt;br /&gt;
    source $HOME/dev/python/ops/bin/activate&lt;br /&gt;
    pip install -r requirements.txt&lt;br /&gt;
&lt;br /&gt;
==== Datacube ====&lt;br /&gt;
&lt;br /&gt;
If you&#039;re in the ops group, you&#039;ll need sometimes to deploy from branches. As our deployment server Complector doesn&#039;t have PHP installed (so no arc), you need to exchange branches through our datacube.&lt;br /&gt;
&lt;br /&gt;
On WindRiver:&lt;br /&gt;
&lt;br /&gt;
     git remote add datacube /datacube/git/operations.git&lt;br /&gt;
&lt;br /&gt;
Anywhere else:&lt;br /&gt;
&lt;br /&gt;
     git remote add datacube ssh://windriver.nasqueron.org/datacube/git/operations.git&lt;br /&gt;
&lt;br /&gt;
If you aren&#039;t in the ops groups, and have access to our devserver, you&#039;ll still be able to clone or pull from that directory, but not to write there (ie push branches).&lt;br /&gt;
&lt;br /&gt;
=== Local computer setup ===&lt;br /&gt;
&lt;br /&gt;
This section cover topics NOT needed on our development servers.&lt;br /&gt;
&lt;br /&gt;
==== macOS ====&lt;br /&gt;
&lt;br /&gt;
To run tests properly, install first:&lt;br /&gt;
&lt;br /&gt;
    brew install bats&lt;br /&gt;
    brew install python3.13&lt;br /&gt;
&lt;br /&gt;
After loading the virtual environment (see everywhere setup), you can install Salt:&lt;br /&gt;
&lt;br /&gt;
    pip install salt==3006.25&lt;br /&gt;
&lt;br /&gt;
Check the version on WindRiver or Complector with &amp;lt;code&amp;gt;salt --versions&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Finally, to run the tests, you need a recent version of make, but the BSD make currently shipped, as of Tahoe 26.5, isn&#039;t up-to-date:&lt;br /&gt;
&lt;br /&gt;
    brew install gmake&lt;br /&gt;
    (cd _tests &amp;amp;&amp;amp; gmake)&lt;br /&gt;
&lt;br /&gt;
==== Arcanist ====&lt;br /&gt;
&lt;br /&gt;
To use arc with the operations repository, our collection of patches is needed.&lt;br /&gt;
&lt;br /&gt;
If arcanist isn&#039;t installed through Git repository, best is to do like on devserver role:&lt;br /&gt;
&lt;br /&gt;
    mkdir /opt/phabricator &amp;amp;&amp;amp; cd /opt/phabricator&lt;br /&gt;
    git clone https://github.com/nasqueron/arcanist.git&lt;br /&gt;
    (cd arcanist &amp;amp;&amp;amp; git checkout production)&lt;br /&gt;
    ln -s /opt/phabricator/arcanist/bin/arc /usr/local/bin/&lt;br /&gt;
    git clone https://devcentral.nasqueron.org/source/shellcheck-linter.git&lt;br /&gt;
&lt;br /&gt;
If you&#039;ve already cloned Arcanist repository, switch to our branch production:&lt;br /&gt;
&lt;br /&gt;
    git remote add nasqueron git@github.com:nasqueron/arcanist.git&lt;br /&gt;
    git fetch --all&lt;br /&gt;
    git checkout production&lt;br /&gt;
&lt;br /&gt;
As of August 2024, there is no plan to make that repository available on DevCentral.&lt;br /&gt;
&lt;br /&gt;
You&#039;ll also need shellcheck library-linter library, normally at the same level than your arcanist repository.&lt;br /&gt;
&lt;br /&gt;
==== IDE configuration ====&lt;br /&gt;
[[File:PyCharm-TemplateLanguages.png|thumb|right|Screenshot of correctly configured template languages]]&lt;br /&gt;
The states .sls file are Jinja2 templates producing YAML files, or &amp;quot;jinja2+yaml&amp;quot;. If this case can&#039;t be handled by your IDE, it works best to use YAML syntax highlighting.&lt;br /&gt;
&lt;br /&gt;
If you use PyCharm or IntelliJ IDEA Ultimate, you can configure this scheme:&lt;br /&gt;
&lt;br /&gt;
* Allow YAML files to be Jinja2 templates&lt;br /&gt;
** Go to Settings &amp;gt; Languages &amp;amp; Frameworks &amp;gt; Template Languages&lt;br /&gt;
** Select Jinja2 as template language&lt;br /&gt;
** Add YAML in the list&lt;br /&gt;
* Open SLS as YAML&lt;br /&gt;
&lt;br /&gt;
== Linting ==&lt;br /&gt;
&lt;br /&gt;
=== pre-commit ===&lt;br /&gt;
You can use &#039;&#039;&#039;pre-commit&#039;&#039;&#039; you can install with &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; to get a hook running Python code to lint the repository before a commit.&lt;br /&gt;
&lt;br /&gt;
Beware if you use &amp;lt;code&amp;gt;arc diff&amp;lt;/code&amp;gt; without a commit first: your message will be lost if pre-commit raises an error, always use &amp;lt;code&amp;gt;git commit&amp;lt;/code&amp;gt; first.&lt;br /&gt;
&lt;br /&gt;
On FreeBSD, there is an issue to build with clang 16+ the ruamel yaml clib library. You can build the FreeBSD port devel/py-ruamel.yaml.clib and copy the .whl to a stable path, then install it in your virtual environment.&lt;br /&gt;
&lt;br /&gt;
On WindRiver, the .whl is available in /opt/python/py311, so you can:&lt;br /&gt;
&lt;br /&gt;
    $ python3 -m venv /path/to/your/virtualenv&lt;br /&gt;
    $ source /path/to/your/virtualenv/bin/activate&lt;br /&gt;
    $ pip install /opt/python/py311/ruamel.yaml.clib-0.2.8-cp311-cp311-freebsd_14_0_release_p3_amd64.whl&lt;br /&gt;
    $ pip install pre-commit&lt;br /&gt;
    $ make&lt;br /&gt;
    pre-commit install&lt;br /&gt;
    pre-commit installed at .git/hooks/pre-commit&lt;br /&gt;
    $ rehash&lt;br /&gt;
    $ pre-commit&lt;br /&gt;
&lt;br /&gt;
== Refactoring ==&lt;br /&gt;
&lt;br /&gt;
=== Rename a lot of files ===&lt;br /&gt;
&lt;br /&gt;
To move a directory and rename the &#039;&#039;Source file&#039;&#039; headers:&lt;br /&gt;
&lt;br /&gt;
    git mv roles/webserver-legacy/nginx/files roles/webserver-alkane/nginx/&lt;br /&gt;
    cd roles/webserver-alkane/nginx/&lt;br /&gt;
    find . -type f -name &#039;*.conf&#039; | xargs gsed -i s/webserver-legacy/webserver-alkane/g&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
* [[/FAQ]] - Frequently asked questions about the Operations repository&lt;br /&gt;
* [[How to contribute code]]&lt;br /&gt;
* [[Devserver reference]]&lt;/div&gt;</summary>
		<author><name>Dereckson</name></author>
	</entry>
	<entry>
		<id>https://agora.nasqueron.org/index.php?title=Keruald&amp;diff=2530</id>
		<title>Keruald</title>
		<link rel="alternate" type="text/html" href="https://agora.nasqueron.org/index.php?title=Keruald&amp;diff=2530"/>
		<updated>2026-04-19T10:15:01Z</updated>

		<summary type="html">&lt;p&gt;Dereckson: /* Troubleshoot */ +arc unit&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Keruald&#039;&#039;&#039; is a set of libraries to build PHP applications.&lt;br /&gt;
&lt;br /&gt;
== Libraries ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ List of libraries&lt;br /&gt;
|-&lt;br /&gt;
! Package name !! Description&lt;br /&gt;
|-&lt;br /&gt;
| keruald/omnitools || General purpose library&lt;br /&gt;
|-&lt;br /&gt;
| keruald/globalfunctions || Wrapper to replace our old old sites &amp;quot;core.php&amp;quot; by calls to omnitools&lt;br /&gt;
|-&lt;br /&gt;
| keruald/commands || Create simple CLI application&lt;br /&gt;
|-&lt;br /&gt;
| keruald/report || Reporting library&lt;br /&gt;
|-&lt;br /&gt;
| keruald/health || Site health check&lt;br /&gt;
|-&lt;br /&gt;
| keruald/dockerhub || Docker Hub, managing payload signatures&lt;br /&gt;
|-&lt;br /&gt;
| keruald/github || GitHub payloads for webhooks - managing payload signatures, class representations&lt;br /&gt;
|-&lt;br /&gt;
| keruald/mailgun || Mailgun API client&lt;br /&gt;
|-&lt;br /&gt;
| keruald/database || Database abstraction layer&lt;br /&gt;
|-&lt;br /&gt;
| keruald/broker || Wrapper around brokers like RabbitMQ&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Developer guide ==&lt;br /&gt;
=== Contribution workflow ===&lt;br /&gt;
&lt;br /&gt;
You&#039;ll find the general contribution guide at [[How to contribute code]]. Here some pointers specific for Keruald libraries.&lt;br /&gt;
&lt;br /&gt;
We use a &#039;&#039;&#039;monorepo&#039;&#039;&#039;: clone the rKERUALD repository on DevCentral, you&#039;ll find your library as a direct subdirectory on it.&lt;br /&gt;
&lt;br /&gt;
Each subdirectory matches:&lt;br /&gt;
* a resource folder, not included in packages, if starting by an underscore _ or a dot . &lt;br /&gt;
* a name of a package if starting by a letter, e.g. keruald/commands for commands/&lt;br /&gt;
&lt;br /&gt;
==== New version of a library ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;This should be automated through Jenkins.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
To publish a new version of a library:&lt;br /&gt;
* Create a new tag using library/version format, e.g. foo/1.2.3&lt;br /&gt;
* Run &amp;lt;code&amp;gt;./_utils/repo/export-commits-to-manyrepo.sh foo&amp;lt;/code&amp;gt;&lt;br /&gt;
* Tag with versions the new commits in the library repository (tags propagation isn&#039;t currently automated)&lt;br /&gt;
** compare &amp;lt;code&amp;gt;git log&amp;lt;/code&amp;gt; from monorepo and library repo&lt;br /&gt;
** Add tag without any prefix in library repo, e.g. &amp;lt;code&amp;gt;git tag 1.2.3&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How to import an existing library? ===&lt;br /&gt;
&lt;br /&gt;
First, use [https://github.com/hraban/tomono tomono] in the PARENT DIRECTORY of the monorepo directory.&lt;br /&gt;
&lt;br /&gt;
If the name of the repository is NOT &amp;quot;core&amp;quot;, export it as MONOREPO_NAME environment variable.&lt;br /&gt;
&lt;br /&gt;
For example, to import Keruald/GitHub library:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;&lt;br /&gt;
$ export MONOREPO_NAME=keruald&lt;br /&gt;
$ echo &amp;quot;ssh://vcs@devcentral.nasqueron.org:5022/source/github.git github&amp;quot; | tomono --continue&lt;br /&gt;
From ssh://devcentral.nasqueron.org:5022/source/github&lt;br /&gt;
 * [new branch]      main       -&amp;gt; github/main&lt;br /&gt;
 * [new tag]         0.1.0      -&amp;gt; github/0.1.0&lt;br /&gt;
 * [new tag]         0.1.1      -&amp;gt; github/0.1.1&lt;br /&gt;
 * [new tag]         0.2.0      -&amp;gt; github/0.2.0&lt;br /&gt;
 * [new tag]         0.2.1      -&amp;gt; github/0.2.1&lt;br /&gt;
Updated 6 paths from the index&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then follow the procedure for a new library to update the monorepo metadata.&lt;br /&gt;
&lt;br /&gt;
Don&#039;t forget to use &amp;lt;code&amp;gt;composer dump-autoload&amp;lt;/code&amp;gt; to update your local Composer autoloader.&lt;br /&gt;
&lt;br /&gt;
=== How to create a new library? ===&lt;br /&gt;
To create a new library quux, we need a new empty manyrepo on DevCentral, a mirror on GitHub and to declare it on Packagist:&lt;br /&gt;
&lt;br /&gt;
# Declare your library in &amp;lt;code&amp;gt;metadata.yml&amp;lt;/code&amp;gt;&lt;br /&gt;
# Regenerate shared files with &amp;lt;code&amp;gt;make regenerate&amp;lt;/code&amp;gt; (you need Python and Jinja2): that will add your repository to files like phpcs.xml&lt;br /&gt;
# Create on DevCentral a new repository with a callsign starting by K for Keruald like KQUUX, and &amp;quot;quux&amp;quot; as shortname&lt;br /&gt;
# Create on GitHub a new repository called keruald/quux&lt;br /&gt;
# Publish on packagist&lt;br /&gt;
&lt;br /&gt;
If the shortname is already taken on DevCentral, it&#039;s time to create a new task to provide a map of subdirectory/package repository.&lt;br /&gt;
&lt;br /&gt;
Don&#039;t commit anything in newly created repos but contribute as usual by creating quux/ subdirectory in the monorepo&lt;br /&gt;
&lt;br /&gt;
=== Troubleshoot ===&lt;br /&gt;
==== Run Arcanist unit tests ====&lt;br /&gt;
Before running an arc unit or arc diff command, you need to set the XDEBUG_MODE environment variable to &amp;quot;coverage&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This is done automatically by the Arcanist code installed on devserver role. For local development, use arcanist with the patches from our production branch. It&#039;s available at https://github.com/nasqueron/arcanist&lt;br /&gt;
&lt;br /&gt;
==== Error: Class &amp;quot;Keruald\GitHub\XHubSignature&amp;quot; not found ====&lt;br /&gt;
When a new library is added to the repository, a new entry is added to composer.json to provide that library.&lt;br /&gt;
&lt;br /&gt;
The Composer autoloader needs then to be updated with &amp;lt;code&amp;gt;composer dump-autoload&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Annex A. IDE configuration ===&lt;br /&gt;
==== PhpStorm ====&lt;br /&gt;
&lt;br /&gt;
Clone the monorepo on your drive, then open it in PhpStorm to generate an .idea folder.&lt;br /&gt;
&lt;br /&gt;
* Edit keruald.iml with this modules content to declare the code namespaces: https://devcentral.nasqueron.org/P300&lt;br /&gt;
* For code style, you can use https://github.com/nasqueron/codestyle/blob/main/JetBrains/php-codestyle.xml&lt;/div&gt;</summary>
		<author><name>Dereckson</name></author>
	</entry>
	<entry>
		<id>https://agora.nasqueron.org/index.php?title=User:Dereckson/Devserver&amp;diff=2529</id>
		<title>User:Dereckson/Devserver</title>
		<link rel="alternate" type="text/html" href="https://agora.nasqueron.org/index.php?title=User:Dereckson/Devserver&amp;diff=2529"/>
		<updated>2026-04-13T12:44:02Z</updated>

		<summary type="html">&lt;p&gt;Dereckson: Log is available per D4057&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== MediaWiki ==&lt;br /&gt;
=== Logs ===&lt;br /&gt;
tail -n 100 -f /var/log/www/dereckson.be/mediawiki-php.log&lt;br /&gt;
&lt;br /&gt;
=== Reinstall ===&lt;br /&gt;
* /var/51-wwwroot/mediawiki-dereckson/core: wikimedia/core repository&lt;br /&gt;
* /var/51-wwwroot/mediawiki-dereckson/core/extensions: symlink to &amp;lt;code&amp;gt;../extensions&amp;lt;/code&amp;gt;&lt;br /&gt;
** Clone all needed extensions in /var/51-wwwroot/mediawiki-dereckson/extensions&lt;br /&gt;
* /var/51-wwwroot/mediawiki-dereckson/core/skins: symlink to &amp;lt;code&amp;gt;../skins&amp;lt;/code&amp;gt;&lt;br /&gt;
** Same with git clone ssh://review/mediawiki/skins/&lt;br /&gt;
* /var/dataroot/mediawiki.dereckson.be/data contains:&lt;br /&gt;
** my_wiki.sqlite for the content&lt;br /&gt;
** wikicache.sqlite for the cache&lt;br /&gt;
&lt;br /&gt;
=== Update ===&lt;br /&gt;
* &#039;&#039;&#039;Core:&#039;&#039;&#039; mw-update-core (currently writing it)&lt;br /&gt;
&lt;br /&gt;
=== Create a new extension ===&lt;br /&gt;
;I. Wikimedia side&lt;br /&gt;
* [[mw:Manual:Developing_extensions]] &lt;br /&gt;
* [[mw:Gerrit/New repositories/Requests]]&lt;br /&gt;
* [https://phabricator.wikimedia.org/maniphest/task/edit/form/1/?projects=Project-Admins Create task for new Phabricator project]&lt;br /&gt;
&lt;br /&gt;
;II. WindRiver&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;shell&amp;quot;&amp;gt;&lt;br /&gt;
$ setenv MW_EXTENSION foo&lt;br /&gt;
$ cd ~/dev/wikimedia/mediawiki/extensions&lt;br /&gt;
$ git clone ssh://review/mediawiki/extensions/$MW_EXTENSION || git init $MW_EXTENSION &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Extension is actually stored at /var/51-wwwroot/mediawiki-dereckson/extensions, so can immediately be configured to test locally.&lt;br /&gt;
&lt;br /&gt;
;III. SaaS deployment&lt;br /&gt;
* {{Ops file|pillar/saas/mediawiki.sls}}&lt;br /&gt;
* [https://devcentral.nasqueron.org/source/saas-mediawiki/browse/main/config/Settings.php config/Settings.php]&lt;br /&gt;
&lt;br /&gt;
=== Troubleshoot ===&lt;br /&gt;
==== SQLite database is read-only ====&lt;br /&gt;
Runtime error near line 2: attempt to write a readonly database (8)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;shell&amp;quot;&amp;gt;&lt;br /&gt;
chown -R web-be-dereckson-mw:dereckson /var/dataroot/mediawiki.dereckson.be/data&lt;br /&gt;
chmod 771 /var/dataroot/mediawiki.dereckson.be/data&lt;br /&gt;
chmod 660 /var/dataroot/mediawiki.dereckson.be/data/my_wiki.sqlite&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Permissions to run tests and maintenance scripts ===&lt;br /&gt;
To run tests against wiki and maintenance scripts as user can be tricky:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;shell&amp;quot;&amp;gt;&lt;br /&gt;
touch /tmp/mw-GlobalIdGenerator5001-UID-nodeid /tmp/mw-GlobalIdGenerator5001-UUID-128&lt;br /&gt;
chown web-be-dereckson-mw:dereckson /tmp/mw-GlobalIdGenerator5001-*&lt;br /&gt;
chmod 664 /tmp/mw-GlobalIdGenerator5001-*&lt;br /&gt;
&lt;br /&gt;
chmod 771 /var/dataroot/mediawiki.dereckson.be/data/locks&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Zed ==&lt;br /&gt;
=== Useful paths ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Paths for Zed development&lt;br /&gt;
|-&lt;br /&gt;
! File path !! Managed by !! Notes&lt;br /&gt;
|-&lt;br /&gt;
| /usr/local/etc/nginx/vhosts/dereckson.be/zed51.conf || Salt :: webserver-alkane&lt;br /&gt;
|-&lt;br /&gt;
| /var/51-wwwroot/zed/ || Salt :: wwwroot-51 (still to do) || Git repo: git@github.com:dereckson/zed.git&lt;br /&gt;
|-&lt;br /&gt;
| /var/dataroot/zed/content/ || Manually || Git repo: git@github.com:hypership/content.git&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Logs ===&lt;br /&gt;
* nginx: &amp;lt;code&amp;gt;tail -n 100 -f /var/log/www/dereckson.be/zed51-error.log&amp;lt;/code&amp;gt;&lt;br /&gt;
* PHP: &amp;lt;code&amp;gt;tail -n 100 -f /var/log/www/dereckson.be/zed51-php.log&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Staging  ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note. Keruald is currently symlinked from the monorepo to vendor/keruald.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
To recreate Zed staging area:&lt;br /&gt;
&lt;br /&gt;
    $ cd /var/dataroot/zed/content&lt;br /&gt;
    $ git init .&lt;br /&gt;
    $ git config --global --add safe.directory /var/dataroot/zed/content&lt;br /&gt;
    $ git remote add origin git@github.com:hypership/content.git&lt;br /&gt;
    $ git fetch --all&lt;br /&gt;
    $ git reset --hard origin/main&lt;br /&gt;
    $ git clone git@github.com:hypership/content_users.git users&lt;br /&gt;
    &lt;br /&gt;
    $ sudo -u web-be-dereckson-zed51 mkdir /var/dataroot/zed/cache/sessions&lt;br /&gt;
    $ sudo mkdir -p /var/dataroot/zed/content/users/_photos/tn&lt;br /&gt;
    $ sudo chown -R web-be-dereckson-zed51:dereckson /var/dataroot/zed/content/users/_photos&lt;br /&gt;
    $ sudo chmod 771 /var/dataroot/zed/content/users/_photos /var/dataroot/zed/content/users/_photos/tn&lt;br /&gt;
    &lt;br /&gt;
    $ mkdir -p /home/dereckson/dev/zed/hypership&lt;br /&gt;
    $ cd /home/dereckson/dev/zed/hypership&lt;br /&gt;
    $ ln -s /var/dataroot/zed/content&lt;br /&gt;
    &lt;br /&gt;
Note: Zed currently not defined in wwwroot-51 in rOPS, should be done for /var/51-wwwroot/zed&lt;br /&gt;
&lt;br /&gt;
== IRC ==&lt;br /&gt;
&lt;br /&gt;
=== Troubleshoot ===&lt;br /&gt;
==== Error loading module proxy/irc ====&lt;br /&gt;
When trying to load proxy module, I got:&lt;br /&gt;
&lt;br /&gt;
    22:00:09 -!- Irssi: Error loading module proxy/irc: /home/dereckson/.irssi/modules/libirc_proxy.so: Undefined symbol &amp;quot;g_input_add&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Proxy is now compiled by default, personal module needs to be deleted.&lt;/div&gt;</summary>
		<author><name>Dereckson</name></author>
	</entry>
	<entry>
		<id>https://agora.nasqueron.org/index.php?title=User:Dereckson/Devserver&amp;diff=2528</id>
		<title>User:Dereckson/Devserver</title>
		<link rel="alternate" type="text/html" href="https://agora.nasqueron.org/index.php?title=User:Dereckson/Devserver&amp;diff=2528"/>
		<updated>2026-04-13T12:19:27Z</updated>

		<summary type="html">&lt;p&gt;Dereckson: /* Zed */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== MediaWiki ==&lt;br /&gt;
=== Logs ===&lt;br /&gt;
tail -n 100 -f /var/log/www/dereckson.be/mediawiki-php.log&lt;br /&gt;
&lt;br /&gt;
=== Reinstall ===&lt;br /&gt;
* /var/51-wwwroot/mediawiki-dereckson/core: wikimedia/core repository&lt;br /&gt;
* /var/51-wwwroot/mediawiki-dereckson/core/extensions: symlink to &amp;lt;code&amp;gt;../extensions&amp;lt;/code&amp;gt;&lt;br /&gt;
** Clone all needed extensions in /var/51-wwwroot/mediawiki-dereckson/extensions&lt;br /&gt;
* /var/51-wwwroot/mediawiki-dereckson/core/skins: symlink to &amp;lt;code&amp;gt;../skins&amp;lt;/code&amp;gt;&lt;br /&gt;
** Same with git clone ssh://review/mediawiki/skins/&lt;br /&gt;
* /var/dataroot/mediawiki.dereckson.be/data contains:&lt;br /&gt;
** my_wiki.sqlite for the content&lt;br /&gt;
** wikicache.sqlite for the cache&lt;br /&gt;
&lt;br /&gt;
=== Update ===&lt;br /&gt;
* &#039;&#039;&#039;Core:&#039;&#039;&#039; mw-update-core (currently writing it)&lt;br /&gt;
&lt;br /&gt;
=== Create a new extension ===&lt;br /&gt;
;I. Wikimedia side&lt;br /&gt;
* [[mw:Manual:Developing_extensions]] &lt;br /&gt;
* [[mw:Gerrit/New repositories/Requests]]&lt;br /&gt;
* [https://phabricator.wikimedia.org/maniphest/task/edit/form/1/?projects=Project-Admins Create task for new Phabricator project]&lt;br /&gt;
&lt;br /&gt;
;II. WindRiver&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;shell&amp;quot;&amp;gt;&lt;br /&gt;
$ setenv MW_EXTENSION foo&lt;br /&gt;
$ cd ~/dev/wikimedia/mediawiki/extensions&lt;br /&gt;
$ git clone ssh://review/mediawiki/extensions/$MW_EXTENSION || git init $MW_EXTENSION &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Extension is actually stored at /var/51-wwwroot/mediawiki-dereckson/extensions, so can immediately be configured to test locally.&lt;br /&gt;
&lt;br /&gt;
;III. SaaS deployment&lt;br /&gt;
* {{Ops file|pillar/saas/mediawiki.sls}}&lt;br /&gt;
* [https://devcentral.nasqueron.org/source/saas-mediawiki/browse/main/config/Settings.php config/Settings.php]&lt;br /&gt;
&lt;br /&gt;
=== Troubleshoot ===&lt;br /&gt;
==== SQLite database is read-only ====&lt;br /&gt;
Runtime error near line 2: attempt to write a readonly database (8)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;shell&amp;quot;&amp;gt;&lt;br /&gt;
chown -R web-be-dereckson-mw:dereckson /var/dataroot/mediawiki.dereckson.be/data&lt;br /&gt;
chmod 771 /var/dataroot/mediawiki.dereckson.be/data&lt;br /&gt;
chmod 660 /var/dataroot/mediawiki.dereckson.be/data/my_wiki.sqlite&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Permissions to run tests and maintenance scripts ===&lt;br /&gt;
To run tests against wiki and maintenance scripts as user can be tricky:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;shell&amp;quot;&amp;gt;&lt;br /&gt;
touch /tmp/mw-GlobalIdGenerator5001-UID-nodeid /tmp/mw-GlobalIdGenerator5001-UUID-128&lt;br /&gt;
chown web-be-dereckson-mw:dereckson /tmp/mw-GlobalIdGenerator5001-*&lt;br /&gt;
chmod 664 /tmp/mw-GlobalIdGenerator5001-*&lt;br /&gt;
&lt;br /&gt;
chmod 771 /var/dataroot/mediawiki.dereckson.be/data/locks&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Zed ==&lt;br /&gt;
=== Useful paths ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Paths for Zed development&lt;br /&gt;
|-&lt;br /&gt;
! File path !! Managed by !! Notes&lt;br /&gt;
|-&lt;br /&gt;
| /usr/local/etc/nginx/vhosts/dereckson.be/zed51.conf || Salt :: webserver-alkane&lt;br /&gt;
|-&lt;br /&gt;
| /var/51-wwwroot/zed/ || Salt :: wwwroot-51 (still to do) || Git repo: git@github.com:dereckson/zed.git&lt;br /&gt;
|-&lt;br /&gt;
| /var/dataroot/zed/content/ || Manually || Git repo: git@github.com:hypership/content.git&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Logs ===&lt;br /&gt;
* nginx: &amp;lt;code&amp;gt;tail -n 100 -f $LOG&amp;lt;/code&amp;gt; - still to provision, currently general one&lt;br /&gt;
* PHP: &amp;lt;code&amp;gt;tail -n 100 -f /var/log/www/dereckson.be/zed51-php.log&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Staging  ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note. Keruald is currently symlinked from the monorepo to vendor/keruald.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
To recreate Zed staging area:&lt;br /&gt;
&lt;br /&gt;
    $ cd /var/dataroot/zed/content&lt;br /&gt;
    $ git init .&lt;br /&gt;
    $ git config --global --add safe.directory /var/dataroot/zed/content&lt;br /&gt;
    $ git remote add origin git@github.com:hypership/content.git&lt;br /&gt;
    $ git fetch --all&lt;br /&gt;
    $ git reset --hard origin/main&lt;br /&gt;
    $ git clone git@github.com:hypership/content_users.git users&lt;br /&gt;
    &lt;br /&gt;
    $ sudo -u web-be-dereckson-zed51 mkdir /var/dataroot/zed/cache/sessions&lt;br /&gt;
    $ sudo mkdir -p /var/dataroot/zed/content/users/_photos/tn&lt;br /&gt;
    $ sudo chown -R web-be-dereckson-zed51:dereckson /var/dataroot/zed/content/users/_photos&lt;br /&gt;
    $ sudo chmod 771 /var/dataroot/zed/content/users/_photos /var/dataroot/zed/content/users/_photos/tn&lt;br /&gt;
    &lt;br /&gt;
    $ mkdir -p /home/dereckson/dev/zed/hypership&lt;br /&gt;
    $ cd /home/dereckson/dev/zed/hypership&lt;br /&gt;
    $ ln -s /var/dataroot/zed/content&lt;br /&gt;
    &lt;br /&gt;
Note: Zed currently not defined in wwwroot-51 in rOPS, should be done for /var/51-wwwroot/zed&lt;br /&gt;
&lt;br /&gt;
== IRC ==&lt;br /&gt;
&lt;br /&gt;
=== Troubleshoot ===&lt;br /&gt;
==== Error loading module proxy/irc ====&lt;br /&gt;
When trying to load proxy module, I got:&lt;br /&gt;
&lt;br /&gt;
    22:00:09 -!- Irssi: Error loading module proxy/irc: /home/dereckson/.irssi/modules/libirc_proxy.so: Undefined symbol &amp;quot;g_input_add&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Proxy is now compiled by default, personal module needs to be deleted.&lt;/div&gt;</summary>
		<author><name>Dereckson</name></author>
	</entry>
	<entry>
		<id>https://agora.nasqueron.org/index.php?title=Module:ProjectBox&amp;diff=2527</id>
		<title>Module:ProjectBox</title>
		<link rel="alternate" type="text/html" href="https://agora.nasqueron.org/index.php?title=Module:ProjectBox&amp;diff=2527"/>
		<updated>2026-04-09T17:52:40Z</updated>

		<summary type="html">&lt;p&gt;Dereckson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;-- Module:ProjectInfobox&lt;br /&gt;
-- Renders a structured infobox for a project page.&lt;br /&gt;
-- Usage: {{#invoke:ProjectInfobox|render}}&lt;br /&gt;
&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
-- Split a comma-separated string into a trimmed list.&lt;br /&gt;
local function splitList(value)&lt;br /&gt;
    local items = {}&lt;br /&gt;
    for item in value:gmatch(&amp;quot;[^,]+&amp;quot;) do&lt;br /&gt;
        table.insert(items, mw.text.trim(item))&lt;br /&gt;
    end&lt;br /&gt;
    return items&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Wrap a value in a table cell pair (label / value).&lt;br /&gt;
local function row(label, value)&lt;br /&gt;
    return mw.html.create(&amp;quot;tr&amp;quot;)&lt;br /&gt;
        :tag(&amp;quot;th&amp;quot;):addClass(&amp;quot;project-infobox__label&amp;quot;):wikitext(label):done()&lt;br /&gt;
        :tag(&amp;quot;td&amp;quot;):addClass(&amp;quot;project-infobox__value&amp;quot;):wikitext(value):done()&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Render participants as a comma-separated inline list.&lt;br /&gt;
local function participantCell(raw)&lt;br /&gt;
    local names = splitList(raw)&lt;br /&gt;
    local linked = {}&lt;br /&gt;
    for _, name in ipairs(names) do&lt;br /&gt;
        table.insert(linked, &amp;quot;[[User:&amp;quot; .. name .. &amp;quot;|&amp;quot; .. name .. &amp;quot;]]&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
    return table.concat(linked, &amp;quot;, &amp;quot;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.render(frame)&lt;br /&gt;
    local args = frame:getParent().args&lt;br /&gt;
&lt;br /&gt;
    local group        = mw.text.trim(args.group        or &amp;quot;&amp;quot;)&lt;br /&gt;
    local project      = mw.text.trim(args.project      or &amp;quot;&amp;quot;)&lt;br /&gt;
    local participants = mw.text.trim(args.participants or &amp;quot;&amp;quot;)&lt;br /&gt;
    local status       = mw.text.trim(args.status      or &amp;quot;&amp;quot;)&lt;br /&gt;
    local description  = mw.text.trim(args.description or &amp;quot;&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    local root  = mw.html.create(&amp;quot;table&amp;quot;):addClass(&amp;quot;project-infobox&amp;quot;)&lt;br /&gt;
    local tbody = root:tag(&amp;quot;tbody&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    -- Header row: project name as caption&lt;br /&gt;
    root:tag(&amp;quot;caption&amp;quot;)&lt;br /&gt;
        :addClass(&amp;quot;project-infobox__title&amp;quot;)&lt;br /&gt;
        :wikitext(project ~= &amp;quot;&amp;quot; and project or &amp;quot;Project&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    if group ~= &amp;quot;&amp;quot; then&lt;br /&gt;
        tbody:node(row(&amp;quot;Group&amp;quot;, group))&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if project ~= &amp;quot;&amp;quot; then&lt;br /&gt;
        tbody:node(row(&amp;quot;Project&amp;quot;, project))&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if status ~= &amp;quot;&amp;quot; then&lt;br /&gt;
        tbody:node(row(&amp;quot;Status&amp;quot;, status))&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if participants ~= &amp;quot;&amp;quot; then&lt;br /&gt;
        tbody:node(row(&amp;quot;Participants&amp;quot;, participantCell(participants)))&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if description ~= &amp;quot;&amp;quot; then&lt;br /&gt;
        tbody:tag(&amp;quot;tr&amp;quot;)&lt;br /&gt;
            :tag(&amp;quot;td&amp;quot;)&lt;br /&gt;
                :attr(&amp;quot;colspan&amp;quot;, &amp;quot;2&amp;quot;)&lt;br /&gt;
                :addClass(&amp;quot;project-infobox__description&amp;quot;)&lt;br /&gt;
                :wikitext(description)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return tostring(root)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Dereckson</name></author>
	</entry>
	<entry>
		<id>https://agora.nasqueron.org/index.php?title=Module:ProjectBox&amp;diff=2526</id>
		<title>Module:ProjectBox</title>
		<link rel="alternate" type="text/html" href="https://agora.nasqueron.org/index.php?title=Module:ProjectBox&amp;diff=2526"/>
		<updated>2026-04-09T17:41:03Z</updated>

		<summary type="html">&lt;p&gt;Dereckson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;local p = {}&lt;br /&gt;
&lt;br /&gt;
local function renderRow(label, value)&lt;br /&gt;
    if not value or value == &amp;quot;&amp;quot; then&lt;br /&gt;
        return &amp;quot;&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
    return string.format(&lt;br /&gt;
        &#039;&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;%s&amp;lt;/th&amp;gt;&amp;lt;td&amp;gt;%s&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&#039;,&lt;br /&gt;
        label, value&lt;br /&gt;
    )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.render(frame)&lt;br /&gt;
    local args = frame:getParent().args&lt;br /&gt;
&lt;br /&gt;
    local html = {}&lt;br /&gt;
&lt;br /&gt;
    table.insert(html, &#039;&amp;lt;table class=&amp;quot;infobox project-infobox&amp;quot;&amp;gt;&#039;)&lt;br /&gt;
&lt;br /&gt;
    -- Title&lt;br /&gt;
    if args.project and args.project ~= &amp;quot;&amp;quot; then&lt;br /&gt;
        table.insert(html,&lt;br /&gt;
            string.format(&#039;&amp;lt;tr&amp;gt;&amp;lt;th colspan=&amp;quot;2&amp;quot; class=&amp;quot;infobox-title&amp;quot;&amp;gt;%s&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&#039;, args.project)&lt;br /&gt;
        )&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    -- Rows&lt;br /&gt;
    table.insert(html, renderRow(&amp;quot;Group&amp;quot;, args.group))&lt;br /&gt;
    table.insert(html, renderRow(&amp;quot;Participants&amp;quot;, args.participants))&lt;br /&gt;
&lt;br /&gt;
    table.insert(html, &#039;&amp;lt;/table&amp;gt;&#039;)&lt;br /&gt;
&lt;br /&gt;
    return table.concat(html, &#039;\n&#039;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Dereckson</name></author>
	</entry>
	<entry>
		<id>https://agora.nasqueron.org/index.php?title=Module:ProjectBox&amp;diff=2525</id>
		<title>Module:ProjectBox</title>
		<link rel="alternate" type="text/html" href="https://agora.nasqueron.org/index.php?title=Module:ProjectBox&amp;diff=2525"/>
		<updated>2026-04-09T17:38:42Z</updated>

		<summary type="html">&lt;p&gt;Dereckson: Created page with &amp;quot;local p = {}  local function renderRow(label, value)     if not value or value == &amp;quot;&amp;quot; then         return &amp;quot;&amp;quot;     end     return string.format(         &amp;#039;&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;%s&amp;lt;/th&amp;gt;&amp;lt;td&amp;gt;%s&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;#039;,         label, value     ) end  function p.render(frame)     local args = frame:getParent().args      local html = {}     table.insert(html, &amp;#039;{| class=&amp;quot;infobox project-infobox&amp;quot;&amp;#039;)      -- Title (project name)     if args.project then         table.insert(html, string.format(&amp;#039;! colspan=&amp;quot;2&amp;quot; c...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;local p = {}&lt;br /&gt;
&lt;br /&gt;
local function renderRow(label, value)&lt;br /&gt;
    if not value or value == &amp;quot;&amp;quot; then&lt;br /&gt;
        return &amp;quot;&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
    return string.format(&lt;br /&gt;
        &#039;&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;%s&amp;lt;/th&amp;gt;&amp;lt;td&amp;gt;%s&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&#039;,&lt;br /&gt;
        label, value&lt;br /&gt;
    )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.render(frame)&lt;br /&gt;
    local args = frame:getParent().args&lt;br /&gt;
&lt;br /&gt;
    local html = {}&lt;br /&gt;
    table.insert(html, &#039;{| class=&amp;quot;infobox project-infobox&amp;quot;&#039;)&lt;br /&gt;
&lt;br /&gt;
    -- Title (project name)&lt;br /&gt;
    if args.project then&lt;br /&gt;
        table.insert(html, string.format(&#039;! colspan=&amp;quot;2&amp;quot; class=&amp;quot;infobox-title&amp;quot; | %s&#039;, args.project))&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    table.insert(html, &#039;|-&#039;)&lt;br /&gt;
&lt;br /&gt;
    -- Rows&lt;br /&gt;
    table.insert(html, renderRow(&amp;quot;Group&amp;quot;, args.group))&lt;br /&gt;
    table.insert(html, renderRow(&amp;quot;Participants&amp;quot;, args.participants))&lt;br /&gt;
&lt;br /&gt;
    table.insert(html, &#039;|}&#039;)&lt;br /&gt;
&lt;br /&gt;
    return table.concat(html, &#039;\n&#039;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Dereckson</name></author>
	</entry>
	<entry>
		<id>https://agora.nasqueron.org/index.php?title=User:Dereckson/Sandbox&amp;diff=2524</id>
		<title>User:Dereckson/Sandbox</title>
		<link rel="alternate" type="text/html" href="https://agora.nasqueron.org/index.php?title=User:Dereckson/Sandbox&amp;diff=2524"/>
		<updated>2026-04-09T17:37:22Z</updated>

		<summary type="html">&lt;p&gt;Dereckson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#invoke:ProjectBox|render&lt;br /&gt;
 | project = Some project&lt;br /&gt;
 | group = Nasqueron Operations SIG&lt;br /&gt;
 | participants = Dereckson ⬪ ptdradmin&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Dereckson</name></author>
	</entry>
	<entry>
		<id>https://agora.nasqueron.org/index.php?title=User:Dereckson/Sandbox&amp;diff=2523</id>
		<title>User:Dereckson/Sandbox</title>
		<link rel="alternate" type="text/html" href="https://agora.nasqueron.org/index.php?title=User:Dereckson/Sandbox&amp;diff=2523"/>
		<updated>2026-04-09T17:37:10Z</updated>

		<summary type="html">&lt;p&gt;Dereckson: Created page with &amp;quot;{{#invoke:ProjectInfobox|render  | project = Some project  | group = Nasqueron Operations SIG  | participants = Dereckson ⬪ ptdradmin }}&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#invoke:ProjectInfobox|render&lt;br /&gt;
 | project = Some project&lt;br /&gt;
 | group = Nasqueron Operations SIG&lt;br /&gt;
 | participants = Dereckson ⬪ ptdradmin&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Dereckson</name></author>
	</entry>
	<entry>
		<id>https://agora.nasqueron.org/index.php?title=Operations_grimoire/Anubis&amp;diff=2522</id>
		<title>Operations grimoire/Anubis</title>
		<link rel="alternate" type="text/html" href="https://agora.nasqueron.org/index.php?title=Operations_grimoire/Anubis&amp;diff=2522"/>
		<updated>2026-04-09T17:30:58Z</updated>

		<summary type="html">&lt;p&gt;Dereckson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Anubis&#039;&#039;&#039; is a proxy to filter out AI scrapers requests. It will allow sites like [[Operations grimoire/DevCentral|DevCentral]] to stop to serve heavy traffic for LLM model training.&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Challenges ==&lt;br /&gt;
We want to stop scraping traffic, but let legitimate traffic pass (e.g. CLI requests from Conduit).&lt;br /&gt;
&lt;br /&gt;
Anubis is used by a lot of similar software forges from open-source projects: [https://anubis.techaro.lol/docs/user/known-instances Anubis known instances], but it&#039;s unclear if someone already succeed to configure it for Phabricator.&lt;br /&gt;
&lt;br /&gt;
It&#039;s our current field of investigation by Gui and Dereckson.&lt;br /&gt;
&lt;br /&gt;
At Wikimedia, Andrew Kostka (WMDE) has some experience deploying it, apparently for Wikibase products.&lt;br /&gt;
&lt;br /&gt;
== Implementation (by Gui) ==&lt;br /&gt;
=== Isolation via UNIX Sockets ===&lt;br /&gt;
To avoid to maintain a table of TCP ports, each instance is configured to use UNIX sockets for both traffic and metrics:&lt;br /&gt;
* &#039;&#039;&#039;Main socket:&#039;&#039;&#039; &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;/run/anubis/{{ instance }}.sock&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Metrics socket:&#039;&#039;&#039; &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;/run/anubis/{{ instance }}-metrics.sock&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Dynamic Configuration ===&lt;br /&gt;
The Salt states resolve the target application&#039;s port from the `docker_containers` pillar. In `anubis_instances`, we define the target:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
anubis_instances:&lt;br /&gt;
  devcentral:&lt;br /&gt;
    target:&lt;br /&gt;
      service: phabricator&lt;br /&gt;
      container: devcentral&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Provisioning and Vault ===&lt;br /&gt;
Anubis API and Dashboard keys are provisioned in &#039;&#039;&#039;Vault&#039;&#039;&#039; using a helper script [scripts/fix_anubis_devcentral.sh](cci:7://file:///C:/Users/Gui%20Martinien/Downloads/operations-main/operations-main/scripts/fix_anubis_devcentral.sh:0:0-0:0) and retrieved by Salt during deployment.&lt;br /&gt;
&lt;br /&gt;
== Current work ==&lt;br /&gt;
* Gui deployed an experimental run manually on Dwellers to figure how we can build and configure Anubis&lt;br /&gt;
* Work to deploy Anubis with Salt: [https://devcentral.nasqueron.org/D3908 D3908]&lt;br /&gt;
&lt;br /&gt;
== Troubleshoot ==&lt;br /&gt;
=== Each site must have its own Anubis instance ===&lt;br /&gt;
If you serve to protect two different domains, you need two Anubis instances, one per domain.&lt;br /&gt;
&lt;br /&gt;
In December, we noticed strange errors about challenges not found trying to fire the same instance for two different targets from the same domain.&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
* [https://anubis.techaro.lol/ Anubis website]&lt;/div&gt;</summary>
		<author><name>Dereckson</name></author>
	</entry>
	<entry>
		<id>https://agora.nasqueron.org/index.php?title=Operations_grimoire/Anubis&amp;diff=2521</id>
		<title>Operations grimoire/Anubis</title>
		<link rel="alternate" type="text/html" href="https://agora.nasqueron.org/index.php?title=Operations_grimoire/Anubis&amp;diff=2521"/>
		<updated>2026-04-09T17:30:21Z</updated>

		<summary type="html">&lt;p&gt;Dereckson: /* Isolation via UNIX Sockets */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Anubis&#039;&#039;&#039; is a proxy to filter out AI scrapers requests. It will allow sites like [[Operations grimoire/DevCentral|DevCentral]] to stop to serve heavy traffic for LLM model training.&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Challenges ==&lt;br /&gt;
We want to stop scraping traffic, but let legitimate traffic pass (e.g. CLI requests from Conduit).&lt;br /&gt;
&lt;br /&gt;
Anubis is used by a lot of similar software forges from open-source projects: [https://anubis.techaro.lol/docs/user/known-instances Anubis known instances], but it&#039;s unclear if someone already succeed to configure it for Phabricator.&lt;br /&gt;
&lt;br /&gt;
It&#039;s our current field of investigation by Doba Gui and Dereckson.&lt;br /&gt;
&lt;br /&gt;
At Wikimedia, Andrew Kostka (WMDE) has some experience deploying it, apparently for Wikibase products.&lt;br /&gt;
&lt;br /&gt;
== Implementation (by Doba Gui) ==&lt;br /&gt;
=== Isolation via UNIX Sockets ===&lt;br /&gt;
To avoid to maintain a table of TCP ports, each instance is configured to use UNIX sockets for both traffic and metrics:&lt;br /&gt;
* &#039;&#039;&#039;Main socket:&#039;&#039;&#039; &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;/run/anubis/{{ instance }}.sock&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Metrics socket:&#039;&#039;&#039; &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;/run/anubis/{{ instance }}-metrics.sock&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Dynamic Configuration ===&lt;br /&gt;
The Salt states resolve the target application&#039;s port from the `docker_containers` pillar. In `anubis_instances`, we define the target:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
anubis_instances:&lt;br /&gt;
  devcentral:&lt;br /&gt;
    target:&lt;br /&gt;
      service: phabricator&lt;br /&gt;
      container: devcentral&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Provisioning and Vault ===&lt;br /&gt;
Anubis API and Dashboard keys are provisioned in &#039;&#039;&#039;Vault&#039;&#039;&#039; using a helper script [scripts/fix_anubis_devcentral.sh](cci:7://file:///C:/Users/Gui%20Martinien/Downloads/operations-main/operations-main/scripts/fix_anubis_devcentral.sh:0:0-0:0) and retrieved by Salt during deployment.&lt;br /&gt;
&lt;br /&gt;
== Current work ==&lt;br /&gt;
* Doba deployed an experimental run manually on Dwellers to figure how we can build and configure Anubis&lt;br /&gt;
* Work to deploy Anubis with Salt: [https://devcentral.nasqueron.org/D3908 D3908]&lt;br /&gt;
&lt;br /&gt;
== Troubleshoot ==&lt;br /&gt;
=== Each site must have its own Anubis instance ===&lt;br /&gt;
If you serve to protect two different domains, you need two Anubis instances, one per domain.&lt;br /&gt;
&lt;br /&gt;
In December, we noticed strange errors about challenges not found trying to fire the same instance for two different targets from the same domain.&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
* [https://anubis.techaro.lol/ Anubis website]&lt;/div&gt;</summary>
		<author><name>Dereckson</name></author>
	</entry>
	<entry>
		<id>https://agora.nasqueron.org/index.php?title=Operations_grimoire/Configuration_files&amp;diff=2519</id>
		<title>Operations grimoire/Configuration files</title>
		<link rel="alternate" type="text/html" href="https://agora.nasqueron.org/index.php?title=Operations_grimoire/Configuration_files&amp;diff=2519"/>
		<updated>2026-04-05T21:07:45Z</updated>

		<summary type="html">&lt;p&gt;Dereckson: Draft&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page lists configuration files managed by our SaltStack operations repository (rOPS).&lt;br /&gt;
&lt;br /&gt;
Each file is deployed from {{Ops file|roles/}} subfolders. The &#039;&#039;&#039;Full path&#039;&#039;&#039; column shows the path relative to {{Ops file|roles/}}.&lt;br /&gt;
&lt;br /&gt;
== bastion ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
! Unit !! Software !! Full path !! Documentation&lt;br /&gt;
|-&lt;br /&gt;
| sshd-otp || SSH || {{Ops file|roles/bastion/sshd-otp/files/sshd.rc}} || [https://docs.freebsd.org/en/articles/rc-scripting/ RC scripting]&lt;br /&gt;
|-&lt;br /&gt;
| sshd-otp || SSH || {{Ops file|roles/bastion/sshd-otp/files/sshd.rc.conf}} || [[Operations grimoire/Services#FreeBSD_rc|FreeBSD rc]]&lt;br /&gt;
|-&lt;br /&gt;
| sshd-otp || systemd || {{Ops file|roles/bastion/sshd-otp/files/sshd.service}} || [https://www.freedesktop.org/software/systemd/man/ systemd documentation]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== core ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
! Unit !! Software !! Full path !! Documentation&lt;br /&gt;
|-&lt;br /&gt;
| certificates || syslog || {{Ops file|roles/core/certificates/files/acmesh/syslog.conf}} || [https://www.rsyslog.com/doc/ rsyslog documentation]&lt;br /&gt;
|-&lt;br /&gt;
| certificates || Certbot || {{Ops file|roles/core/certificates/files/certbot/cli.ini}} || [https://eff-certbot.readthedocs.io/en/latest/ Certbot documentation]&lt;br /&gt;
|-&lt;br /&gt;
| login || BSD login || {{Ops file|roles/core/login/files/login.conf}} || [https://man.freebsd.org/cgi/man.cgi?login.conf login.conf man page]&lt;br /&gt;
|-&lt;br /&gt;
| monitoring || Prometheus || {{Ops file|roles/core/monitoring/files/prometheus-node-exporter.env}} || [https://prometheus.io/docs/ Prometheus documentation]&lt;br /&gt;
|-&lt;br /&gt;
| monitoring || Prometheus || {{Ops file|roles/core/monitoring/files/rc/prometheus-node-exporter.conf}} || [https://prometheus.io/docs/ Prometheus documentation]&lt;br /&gt;
|-&lt;br /&gt;
| network || dhclient || {{Ops file|roles/core/network/files/FreeBSD/dhclient6.rc}} || [[Operations grimoire/Services#FreeBSD_rc|FreeBSD rc]]&lt;br /&gt;
|-&lt;br /&gt;
| network || dhclient || {{Ops file|roles/core/network/files/FreeBSD/dhclient6.service}} || [https://docs.freebsd.org/en/articles/rc-scripting/ RC scripting]&lt;br /&gt;
|-&lt;br /&gt;
| network || GRE tunnels || {{Ops file|roles/core/network/files/FreeBSD/gre.conf}} || [https://man.freebsd.org/cgi/man.cgi?gre gre man page]&lt;br /&gt;
|-&lt;br /&gt;
| network || GRE tunnels || {{Ops file|roles/core/network/files/FreeBSD/netif_gre.rc}} || [https://man.freebsd.org/cgi/man.cgi?gre gre man page]&lt;br /&gt;
|-&lt;br /&gt;
| network || Network || {{Ops file|roles/core/network/files/FreeBSD/netif_ipv4.rc}} || [https://docs.freebsd.org/en/books/handbook/network/ FreeBSD Handbook - Network]&lt;br /&gt;
|-&lt;br /&gt;
| network || Network || {{Ops file|roles/core/network/files/FreeBSD/netif_ipv6.rc}} || [https://docs.freebsd.org/en/books/handbook/network/ FreeBSD Handbook - Network]&lt;br /&gt;
|-&lt;br /&gt;
| network || Routing || {{Ops file|roles/core/network/files/FreeBSD/route-drake.service}} || [https://docs.freebsd.org/en/articles/rc-scripting/ RC scripting]&lt;br /&gt;
|-&lt;br /&gt;
| network || Routing || {{Ops file|roles/core/network/files/FreeBSD/route_drake.rc}} || [https://man.freebsd.org/cgi/man.cgi?route route man page]&lt;br /&gt;
|-&lt;br /&gt;
| network || Routing || {{Ops file|roles/core/network/files/FreeBSD/router.rc}} || [https://man.freebsd.org/cgi/man.cgi?route route man page]&lt;br /&gt;
|-&lt;br /&gt;
| network || Routing || {{Ops file|roles/core/network/files/FreeBSD/routing_ipv4.rc}} || [[Operations grimoire/Services#FreeBSD_rc|FreeBSD rc]]&lt;br /&gt;
|-&lt;br /&gt;
| network || Routing || {{Ops file|roles/core/network/files/FreeBSD/routing_ipv6.rc}} || [[Operations grimoire/Services#FreeBSD_rc|FreeBSD rc]]&lt;br /&gt;
|-&lt;br /&gt;
| network || Routing || {{Ops file|roles/core/network/files/Linux/routes.conf}} || [https://man7.org/linux/man-pages/man8/ip-route.8.html ip-route man page]&lt;br /&gt;
|-&lt;br /&gt;
| network || Routing || {{Ops file|roles/core/network/files/Linux/routes.service}} || [https://www.freedesktop.org/software/systemd/man/ systemd documentation]&lt;br /&gt;
|-&lt;br /&gt;
| network || dhclient || {{Ops file|roles/core/network/files/dhclient6.conf}} || [https://man.freebsd.org/cgi/man.cgi?dhclient.conf dhclient.conf man page]&lt;br /&gt;
|-&lt;br /&gt;
| network || systemd || {{Ops file|roles/core/network/files/ipv6-tunnels/ipv6-tunnel.service}} || [https://www.freedesktop.org/software/systemd/man/ systemd documentation]&lt;br /&gt;
|-&lt;br /&gt;
| ntp || NTP || {{Ops file|roles/core/ntp/files/rc/ntpd.conf}} || [[Operations grimoire/Services#FreeBSD_rc|FreeBSD rc]]&lt;br /&gt;
|-&lt;br /&gt;
| pf || PF firewall || {{Ops file|roles/core/pf/files/pf.conf}} || [https://man.freebsd.org/cgi/man.cgi?pf.conf pf.conf man page]&lt;br /&gt;
|-&lt;br /&gt;
| pf || PF firewall || {{Ops file|roles/core/pf/files/rc/pf.conf}} || [[Operations grimoire/Services#FreeBSD_rc|FreeBSD rc]]&lt;br /&gt;
|-&lt;br /&gt;
| pf || pflog || {{Ops file|roles/core/pf/files/rc/pflog.conf}} || [[Operations grimoire/Services#FreeBSD_rc|FreeBSD rc]]&lt;br /&gt;
|-&lt;br /&gt;
| rc || locate || {{Ops file|roles/core/rc/files/locate.rc}} || [https://man.freebsd.org/cgi/man.cgi?locate.conf locate.conf man page]&lt;br /&gt;
|-&lt;br /&gt;
| rc || periodic || {{Ops file|roles/core/rc/files/periodic.conf}} || [https://man.freebsd.org/cgi/man.cgi?periodic.conf periodic.conf man page]&lt;br /&gt;
|-&lt;br /&gt;
| rsyslog || rsyslog || {{Ops file|roles/core/rsyslog/files/default.conf}} || [https://www.rsyslog.com/doc/ rsyslog documentation]&lt;br /&gt;
|-&lt;br /&gt;
| salt || Salt || {{Ops file|roles/core/salt/files/rc.conf}} || [https://docs.saltproject.io/ Salt documentation]&lt;br /&gt;
|-&lt;br /&gt;
| salt || Vault || {{Ops file|roles/core/salt/files/vault.conf}} || [https://developer.hashicorp.com/vault/docs Vault documentation]&lt;br /&gt;
|-&lt;br /&gt;
| sshd || SSH || {{Ops file|roles/core/sshd/files/rc.conf}} || [https://man.freebsd.org/cgi/man.cgi?sshd_config sshd_config man page]&lt;br /&gt;
|-&lt;br /&gt;
| sysctl || sysctl || {{Ops file|roles/core/sysctl/files/sysctl.conf}} || [https://man.freebsd.org/cgi/man.cgi?sysctl.conf sysctl.conf man page]&lt;br /&gt;
|-&lt;br /&gt;
| userland-home || nano || {{Ops file|roles/core/userland-home/files/dereckson/.nanorc}} || [https://www.nano-editor.org/dist/latest/nanorc.5.html nanorc man page]&lt;br /&gt;
|-&lt;br /&gt;
| userland-home || Zsh || {{Ops file|roles/core/userland-home/files/dereckson/.zshrc}} || [https://zsh.sourceforge.io/Doc/ Zsh documentation]&lt;br /&gt;
|-&lt;br /&gt;
| userland-home || tmux || {{Ops file|roles/core/userland-home/files/dorianwinty/.tmux.conf}} || [https://man.openbsd.org/tmux tmux man page]&lt;br /&gt;
|-&lt;br /&gt;
| userland-home || Zsh || {{Ops file|roles/core/userland-home/files/dorianwinty/.zshrc}} || [https://zsh.sourceforge.io/Doc/ Zsh documentation]&lt;br /&gt;
|-&lt;br /&gt;
| userland-software || pkg || {{Ops file|roles/core/userland-software/files/sources/FreeBSD.conf}} || [https://man.freebsd.org/cgi/man.cgi?pkg.conf pkg.conf man page]&lt;br /&gt;
|-&lt;br /&gt;
| userland-software || pkg || {{Ops file|roles/core/userland-software/files/sources/Nasqueron.conf}} || [https://man.freebsd.org/cgi/man.cgi?pkg.conf pkg.conf man page]&lt;br /&gt;
|-&lt;br /&gt;
| userland-software || tmux || {{Ops file|roles/core/userland-software/files/tmux.conf}} || [https://man.openbsd.org/tmux tmux man page]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== dbserver-mysql ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
! Unit !! Software !! Full path !! Documentation&lt;br /&gt;
|-&lt;br /&gt;
| grc || grc || {{Ops file|roles/dbserver-mysql/grc/files/grcat.config}} || [https://github.com/garabik/grc grc documentation]&lt;br /&gt;
|-&lt;br /&gt;
| mysql-server || MySQL || {{Ops file|roles/dbserver-mysql/mysql-server/files/conf.d/client.cnf}} || [https://dev.mysql.com/doc/refman/en/ MySQL documentation]&lt;br /&gt;
|-&lt;br /&gt;
| mysql-server || MySQL || {{Ops file|roles/dbserver-mysql/mysql-server/files/conf.d/server.cnf}} || [https://dev.mysql.com/doc/refman/en/ MySQL documentation]&lt;br /&gt;
|-&lt;br /&gt;
| mysql-server || MySQL || {{Ops file|roles/dbserver-mysql/mysql-server/files/mysql.rc}} || [[Operations grimoire/Services#FreeBSD_rc|FreeBSD rc]]&lt;br /&gt;
|-&lt;br /&gt;
| salt || Salt || {{Ops file|roles/dbserver-mysql/salt/files/mysql.conf}} || [https://docs.saltproject.io/ Salt documentation]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== dbserver-pgsql ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
! Unit !! Software !! Full path !! Documentation&lt;br /&gt;
|-&lt;br /&gt;
| server || PostgreSQL || {{Ops file|roles/dbserver-pgsql/server/files/pg_hba.conf}} || [https://www.postgresql.org/docs/current/ PostgreSQL documentation]&lt;br /&gt;
|-&lt;br /&gt;
| server || PostgreSQL || {{Ops file|roles/dbserver-pgsql/server/files/postgresql.conf}} || [https://www.postgresql.org/docs/current/ PostgreSQL documentation]&lt;br /&gt;
|-&lt;br /&gt;
| server || PostgreSQL || {{Ops file|roles/dbserver-pgsql/server/files/postgresql.rc}} || [[Operations grimoire/Services#FreeBSD_rc|FreeBSD rc]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== devserver ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
! Unit !! Software !! Full path !! Documentation&lt;br /&gt;
|-&lt;br /&gt;
| api-exec || API-exec || {{Ops file|roles/devserver/api-exec/files/api-exec.conf}} || &#039;&#039;custom config, still to document&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| api-exec || API-exec || {{Ops file|roles/devserver/api-exec/files/rc/api_exec.conf}} || [https://docs.freebsd.org/en/articles/rc-scripting/ RC scripting]&lt;br /&gt;
|-&lt;br /&gt;
| mail || Sendmail || {{Ops file|roles/devserver/mail/files/sendmail.rc}} || [https://man.freebsd.org/cgi/man.cgi?sendmail sendmail man page]&lt;br /&gt;
|-&lt;br /&gt;
| pkg || pkg || {{Ops file|roles/devserver/pkg/files/nasqueron.conf}} || [https://man.freebsd.org/cgi/man.cgi?pkg.conf pkg.conf man page]&lt;br /&gt;
|-&lt;br /&gt;
| poudriere || poudriere || {{Ops file|roles/devserver/poudriere/files/poudriere.conf}} || [https://github.com/freebsd/poudriere/wiki poudriere documentation]&lt;br /&gt;
|-&lt;br /&gt;
| userland-home || Git || {{Ops file|roles/devserver/userland-home/files/dereckson/.gitconfig}} || [https://git-scm.com/docs/git-config git-config documentation]&lt;br /&gt;
|-&lt;br /&gt;
| userland-home || Mercurial || {{Ops file|roles/devserver/userland-home/files/dereckson/.hgrc}} || [https://www.mercurial-scm.org/doc/hgrc.5.html hgrc man page]&lt;br /&gt;
|-&lt;br /&gt;
| userland-home || Shell || {{Ops file|roles/devserver/userland-home/files/dereckson/.shell.yml}} || &#039;&#039;custom config, still to document&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| userland-home || tmux || {{Ops file|roles/devserver/userland-home/files/dereckson/.tmux.conf}} || [https://man.openbsd.org/tmux tmux man page]&lt;br /&gt;
|-&lt;br /&gt;
| userland-home || Zsh || {{Ops file|roles/devserver/userland-home/files/dereckson/.zshrc-misc-aliases}} || [https://zsh.sourceforge.io/Doc/ Zsh documentation]&lt;br /&gt;
|-&lt;br /&gt;
| userland-software || ccache || {{Ops file|roles/devserver/userland-software/files/ccache.conf}} || [https://ccache.dev/manual/latest.html ccache documentation]&lt;br /&gt;
|-&lt;br /&gt;
| userland-software || make || {{Ops file|roles/devserver/userland-software/files/make.conf}} || [https://man.freebsd.org/cgi/man.cgi?make.conf make.conf man page]&lt;br /&gt;
|-&lt;br /&gt;
| userland-software || Notifications || {{Ops file|roles/devserver/userland-software/files/notifications.conf}} || &#039;&#039;custom config, still to document&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| userland-software || PEFS || {{Ops file|roles/devserver/userland-software/files/pefs.conf}} || [https://wiki.freebsd.org/PEFS PEFS documentation]&lt;br /&gt;
|-&lt;br /&gt;
| userland-software || Transmission || {{Ops file|roles/devserver/userland-software/files/transmission.rc}} || [https://github.com/transmission/transmission/blob/main/docs/Editing-Configuration-Files.md Transmission documentation]&lt;br /&gt;
|-&lt;br /&gt;
| userland-software || URL configuration || {{Ops file|roles/devserver/userland-software/files/url.yml}} || &#039;&#039;custom config, still to document&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| webserver-home || nginx || {{Ops file|roles/devserver/webserver-home/files/001-server.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== dns ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
! Unit !! Software !! Full path !! Documentation&lt;br /&gt;
|-&lt;br /&gt;
| knot || Knot DNS || {{Ops file|roles/dns/knot/files/knot.conf}} || [https://www.knot-dns.cz/docs/ Knot DNS documentation]&lt;br /&gt;
|-&lt;br /&gt;
| knot || Knot DNS || {{Ops file|roles/dns/knot/files/rc/knot.conf}} || [[Operations grimoire/Services#FreeBSD_rc|FreeBSD rc]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== grafana ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
! Unit !! Software !! Full path !! Documentation&lt;br /&gt;
|-&lt;br /&gt;
| grafana || Grafana || {{Ops file|roles/grafana/grafana/files/grafana.ini}} || [https://grafana.com/docs/grafana/latest/ Grafana documentation]&lt;br /&gt;
|-&lt;br /&gt;
| grafana || Grafana || {{Ops file|roles/grafana/grafana/files/rc/grafana.conf}} || [[Operations grimoire/Services#FreeBSD_rc|FreeBSD rc]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== mailserver ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
! Unit !! Software !! Full path !! Documentation&lt;br /&gt;
|-&lt;br /&gt;
| dkim || OpenDKIM || {{Ops file|roles/mailserver/dkim/files/opendkim.conf}} || [http://www.opendkim.org/opendkim.conf.5.html opendkim.conf man page]&lt;br /&gt;
|-&lt;br /&gt;
| dkim || OpenDKIM || {{Ops file|roles/mailserver/dkim/files/rc/opendkim.conf}} || [[Operations grimoire/Services#FreeBSD_rc|FreeBSD rc]]&lt;br /&gt;
|-&lt;br /&gt;
| dovecot || Dovecot || {{Ops file|roles/mailserver/dovecot/files/conf.d/10-auth.conf}} || [https://doc.dovecot.org/ Dovecot documentation]&lt;br /&gt;
|-&lt;br /&gt;
| dovecot || Dovecot || {{Ops file|roles/mailserver/dovecot/files/conf.d/10-mail.conf}} || [https://doc.dovecot.org/ Dovecot documentation]&lt;br /&gt;
|-&lt;br /&gt;
| dovecot || Dovecot || {{Ops file|roles/mailserver/dovecot/files/conf.d/10-main-services.conf}} || [https://doc.dovecot.org/ Dovecot documentation]&lt;br /&gt;
|-&lt;br /&gt;
| dovecot || Dovecot || {{Ops file|roles/mailserver/dovecot/files/conf.d/10-metrics.conf}} || [https://doc.dovecot.org/ Dovecot documentation]&lt;br /&gt;
|-&lt;br /&gt;
| dovecot || Dovecot || {{Ops file|roles/mailserver/dovecot/files/conf.d/10-ssl.conf}} || [https://doc.dovecot.org/ Dovecot documentation]&lt;br /&gt;
|-&lt;br /&gt;
| dovecot || Dovecot || {{Ops file|roles/mailserver/dovecot/files/dovecot.conf}} || [https://doc.dovecot.org/ Dovecot documentation]&lt;br /&gt;
|-&lt;br /&gt;
| vimbadmin || ViMbAdmin || {{Ops file|roles/mailserver/vimbadmin/files/application.ini}} || [https://github.com/opensolutions/ViMbAdmin ViMbAdmin documentation]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== netbox ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
! Unit !! Software !! Full path !! Documentation&lt;br /&gt;
|-&lt;br /&gt;
| netbox || NetBox || {{Ops file|roles/netbox/netbox/files/rc/netbox.rc}} || [[Operations grimoire/Services#FreeBSD_rc|FreeBSD rc]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== opensearch ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
! Unit !! Software !! Full path !! Documentation&lt;br /&gt;
|-&lt;br /&gt;
| dashboards || systemd || {{Ops file|roles/opensearch/dashboards/files/dashboards.service}} || [https://www.freedesktop.org/software/systemd/man/ systemd documentation]&lt;br /&gt;
|-&lt;br /&gt;
| opensearch || OpenSearch || {{Ops file|roles/opensearch/opensearch/files/account.conf}} || [https://opensearch.org/docs/latest/ OpenSearch documentation]&lt;br /&gt;
|-&lt;br /&gt;
| opensearch || OpenSearch || {{Ops file|roles/opensearch/opensearch/files/opensearch.conf}} || [https://opensearch.org/docs/latest/ OpenSearch documentation]&lt;br /&gt;
|-&lt;br /&gt;
| opensearch || systemd || {{Ops file|roles/opensearch/opensearch/files/opensearch.service}} || [https://www.freedesktop.org/software/systemd/man/ systemd documentation]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== paas-docker ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
! Unit !! Software !! Full path !! Documentation&lt;br /&gt;
|-&lt;br /&gt;
| containers || Docker Compose || {{Ops file|roles/paas-docker/containers/files/relay/dev.yml}} || [https://docs.docker.com/compose/ Docker Compose documentation]&lt;br /&gt;
|-&lt;br /&gt;
| containers || Sentry || {{Ops file|roles/paas-docker/containers/files/sentry/etc/config.yml}} || [https://develop.sentry.dev/self-hosted/ Sentry self-hosted documentation]&lt;br /&gt;
|-&lt;br /&gt;
| containers || Symbolicator || {{Ops file|roles/paas-docker/containers/files/symbolicator/config.yml}} || [https://getsentry.github.io/symbolicator/ Symbolicator documentation]&lt;br /&gt;
|-&lt;br /&gt;
| containers || Vault || {{Ops file|roles/paas-docker/containers/files/vault/vault.hcl}} || [https://developer.hashicorp.com/vault/docs Vault documentation]&lt;br /&gt;
|-&lt;br /&gt;
| devel || systemd || {{Ops file|roles/paas-docker/devel/files/socket.conf}} || [https://www.freedesktop.org/software/systemd/man/ systemd documentation]&lt;br /&gt;
|-&lt;br /&gt;
| kernel || tuned || {{Ops file|roles/paas-docker/kernel/files/tuned.conf}} || [https://tuned-project.org/ tuned documentation]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || logrotate || {{Ops file|roles/paas-docker/nginx/files/logrotate/nginx.conf}} || [https://man.freebsd.org/cgi/man.cgi?logrotate logrotate man page]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/paas-docker/nginx/files/vhosts/_default.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/paas-docker/nginx/files/vhosts/acme_dns.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/paas-docker/nginx/files/vhosts/auth-grove.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/paas-docker/nginx/files/vhosts/base/fallback.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/paas-docker/nginx/files/vhosts/base/server.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/paas-docker/nginx/files/vhosts/bugzilla.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/paas-docker/nginx/files/vhosts/cachet.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/paas-docker/nginx/files/vhosts/etherpad.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/paas-docker/nginx/files/vhosts/hauk.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/paas-docker/nginx/files/vhosts/jenkins.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/paas-docker/nginx/files/vhosts/notifications.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/paas-docker/nginx/files/vhosts/openfire.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/paas-docker/nginx/files/vhosts/orbeon.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/paas-docker/nginx/files/vhosts/penpot_web.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/paas-docker/nginx/files/vhosts/phabricator.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/paas-docker/nginx/files/vhosts/pixelfed.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/paas-docker/nginx/files/vhosts/rabbitmq.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/paas-docker/nginx/files/vhosts/registry.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/paas-docker/nginx/files/vhosts/sentry.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/paas-docker/nginx/files/vhosts/tommy.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/paas-docker/nginx/files/vhosts/vault.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| systemd-timers || systemd || {{Ops file|roles/paas-docker/systemd-timers/files/report.service}} || [https://www.freedesktop.org/software/systemd/man/ systemd documentation]&lt;br /&gt;
|-&lt;br /&gt;
| systemd-timers || systemd || {{Ops file|roles/paas-docker/systemd-timers/files/report.timer}} || [https://www.freedesktop.org/software/systemd/man/ systemd documentation]&lt;br /&gt;
|-&lt;br /&gt;
| systemd-unit || systemd || {{Ops file|roles/paas-docker/systemd-unit/files/docker-containers.service}} || [https://www.freedesktop.org/software/systemd/man/ systemd documentation]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== paas-jails ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
! Unit !! Software !! Full path !! Documentation&lt;br /&gt;
|-&lt;br /&gt;
| jails || Jails || {{Ops file|roles/paas-jails/jails/files/ezjail.rc}} || [https://man.freebsd.org/cgi/man.cgi?jail jail man page]&lt;br /&gt;
|-&lt;br /&gt;
| jails || Jails || {{Ops file|roles/paas-jails/jails/files/jail.rc}} || [https://man.freebsd.org/cgi/man.cgi?jail jail man page]&lt;br /&gt;
|-&lt;br /&gt;
| jails || Network || {{Ops file|roles/paas-jails/jails/files/netif.rc}} || [[Operations grimoire/Services#FreeBSD_rc|FreeBSD rc]]&lt;br /&gt;
|-&lt;br /&gt;
| jails || DNS resolver || {{Ops file|roles/paas-jails/jails/files/resolv.conf}} || [https://man.freebsd.org/cgi/man.cgi?resolv.conf resolv.conf man page]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== prometheus ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
! Unit !! Software !! Full path !! Documentation&lt;br /&gt;
|-&lt;br /&gt;
| prometheus || Prometheus || {{Ops file|roles/prometheus/prometheus/files/prometheus.yml}} || [https://prometheus.io/docs/ Prometheus documentation]&lt;br /&gt;
|-&lt;br /&gt;
| prometheus || Prometheus || {{Ops file|roles/prometheus/prometheus/files/rc/prometheus.conf}} || [[Operations grimoire/Services#FreeBSD_rc|FreeBSD rc]]&lt;br /&gt;
|-&lt;br /&gt;
| prometheus || newsyslog || {{Ops file|roles/prometheus/prometheus/files/syslog/newsyslog.conf}} || [https://man.freebsd.org/cgi/man.cgi?newsyslog.conf newsyslog.conf man page]&lt;br /&gt;
|-&lt;br /&gt;
| prometheus || newsyslog || {{Ops file|roles/prometheus/prometheus/files/syslog/prometheus.conf}} || [https://man.freebsd.org/cgi/man.cgi?newsyslog.conf newsyslog.conf man page]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== redis ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
! Unit !! Software !! Full path !! Documentation&lt;br /&gt;
|-&lt;br /&gt;
| server || Redis || {{Ops file|roles/redis/server/files/redis.rc}} || [[Operations grimoire/Services#FreeBSD_rc|FreeBSD rc]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== reports ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
! Unit !! Software !! Full path !! Documentation&lt;br /&gt;
|-&lt;br /&gt;
| rhyne-wyse || Rhyne-Wyse || {{Ops file|roles/reports/rhyne-wyse/files/secrets.conf}} || [https://docs.nasqueron.org/secretsmith/connect.html#configuration-file secretsmith]&lt;br /&gt;
|-&lt;br /&gt;
| rhyne-wyse || Rhyne-Wyse || {{Ops file|roles/reports/rhyne-wyse/files/syslog/rhyne-wyse.conf}} || [https://man.freebsd.org/cgi/man.cgi?syslog.conf(5) syslog.conf]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== router ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
! Unit !! Software !! Full path !! Documentation&lt;br /&gt;
|-&lt;br /&gt;
| carp || CARP || {{Ops file|roles/router/carp/files/carp.conf}} || [https://man.freebsd.org/cgi/man.cgi?carp carp man page]&lt;br /&gt;
|-&lt;br /&gt;
| carp || CARP || {{Ops file|roles/router/carp/files/carp.rc}} || [[Operations grimoire/Services#FreeBSD_rc|FreeBSD rc]]&lt;br /&gt;
|-&lt;br /&gt;
| carp || CARP || {{Ops file|roles/router/carp/files/secrets.conf}} || [https://docs.nasqueron.org/secretsmith/connect.html#configuration-file secretsmith]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== saas-mediawiki ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
! Unit !! Software !! Full path !! Documentation&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/saas-mediawiki/nginx/files/vhosts/nasqueron.org/agora.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/saas-mediawiki/nginx/files/vhosts/nasqueron.org/wikis.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/saas-mediawiki/nginx/files/vhosts/test.ook.space/mediawiki.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| saas || Environment || {{Ops file|roles/saas-mediawiki/saas/files/dot.env}} || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== salt-primary ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
! Unit !! Software !! Full path !! Documentation&lt;br /&gt;
|-&lt;br /&gt;
| api || Salt || {{Ops file|roles/salt-primary/api/files/api.conf}} || [https://docs.saltproject.io/ Salt documentation]&lt;br /&gt;
|-&lt;br /&gt;
| api || Salt || {{Ops file|roles/salt-primary/api/files/salt_api.rc}} || [[Operations grimoire/Services#FreeBSD_rc|FreeBSD rc]]&lt;br /&gt;
|-&lt;br /&gt;
| config || Salt || {{Ops file|roles/salt-primary/config/files/pillar-tower.conf}} || [https://jgraichen.github.io/salt-tower/latest/tower/ salt-tower]&lt;br /&gt;
|-&lt;br /&gt;
| salt-wrapper || Salt || {{Ops file|roles/salt-primary/salt-wrapper/files/salt-wrapper.conf}} || [https://docs.nasqueron.org/salt-wrapper/admin.html#configuration-file salt-wrapper]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== shellserver ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
! Unit !! Software !! Full path !! Documentation&lt;br /&gt;
|-&lt;br /&gt;
| database || MySQL || {{Ops file|roles/shellserver/database/files/my.cnf}} || [https://dev.mysql.com/doc/refman/en/ MySQL documentation]&lt;br /&gt;
|-&lt;br /&gt;
| odderon || systemd || {{Ops file|roles/shellserver/odderon/files/odderon.service}} || [https://www.freedesktop.org/software/systemd/man/ systemd documentation]&lt;br /&gt;
|-&lt;br /&gt;
| odderon || Odderon || {{Ops file|roles/shellserver/odderon/files/servers.ini}} || [https://github.com/JiggyStardust/Odderon Odderon repository]&lt;br /&gt;
|-&lt;br /&gt;
| odderon || Odderon || {{Ops file|roles/shellserver/odderon/files/setup.ini}} || [https://github.com/JiggyStardust/Odderon Odderon repository]&lt;br /&gt;
|-&lt;br /&gt;
| userland-software || nano || {{Ops file|roles/shellserver/userland-software/files/nanorc}} || [https://www.nano-editor.org/dist/latest/nanorc.5.html nanorc man page]&lt;br /&gt;
|-&lt;br /&gt;
| userland-software || oidentd || {{Ops file|roles/shellserver/userland-software/files/oidentd.conf}} || [https://oidentd.janikrabe.com/doc/2.5/manual oidentd documentation]&lt;br /&gt;
|-&lt;br /&gt;
| userland-software || oidentd || {{Ops file|roles/shellserver/userland-software/files/oidentd.rc}} || [[Operations grimoire/Services#FreeBSD_rc|FreeBSD rc]]&lt;br /&gt;
|-&lt;br /&gt;
| vault || Salt || {{Ops file|roles/shellserver/vault/files/salt-vault.conf}} || [https://docs.saltproject.io/ Salt documentation]&lt;br /&gt;
|-&lt;br /&gt;
| vault || Vault || {{Ops file|roles/shellserver/vault/files/salt.hcl}} || [https://developer.hashicorp.com/vault/docs Vault documentation]&lt;br /&gt;
|-&lt;br /&gt;
| vault || Vault || {{Ops file|roles/shellserver/vault/files/vault.hcl}} || [https://developer.hashicorp.com/vault/docs Vault documentation]&lt;br /&gt;
|-&lt;br /&gt;
| vault || systemd || {{Ops file|roles/shellserver/vault/files/vault.service}} || [https://www.freedesktop.org/software/systemd/man/ systemd documentation]&lt;br /&gt;
|-&lt;br /&gt;
| web-hosting || nginx || {{Ops file|roles/shellserver/web-hosting/files/eglide/nginx/vhosts/000-fallback.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| web-hosting || nginx || {{Ops file|roles/shellserver/web-hosting/files/eglide/nginx/vhosts/001-server.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== vault ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
! Unit !! Software !! Full path !! Documentation&lt;br /&gt;
|-&lt;br /&gt;
| policies || Vault || {{Ops file|roles/vault/policies/files/admin.hcl}} || [https://developer.hashicorp.com/vault/tutorials/get-started/introduction-policies Vault policy]&lt;br /&gt;
|-&lt;br /&gt;
| policies || Vault || {{Ops file|roles/vault/policies/files/airflow.hcl}} || [https://developer.hashicorp.com/vault/tutorials/get-started/introduction-policies Vault policy]&lt;br /&gt;
|-&lt;br /&gt;
| policies || Vault || {{Ops file|roles/vault/policies/files/monitoring.hcl}} || [https://developer.hashicorp.com/vault/tutorials/get-started/introduction-policies Vault policy]&lt;br /&gt;
|-&lt;br /&gt;
| policies || Vault || {{Ops file|roles/vault/policies/files/salt-primary.hcl}} || [https://developer.hashicorp.com/vault/tutorials/get-started/introduction-policies Vault policy]&lt;br /&gt;
|-&lt;br /&gt;
| policies || Vault || {{Ops file|roles/vault/policies/files/sentry.hcl}} || [https://developer.hashicorp.com/vault/tutorials/get-started/introduction-policies Vault policy]&lt;br /&gt;
|-&lt;br /&gt;
| policies || Vault || {{Ops file|roles/vault/policies/files/vault_bootstrap.hcl}} || [https://developer.hashicorp.com/vault/tutorials/get-started/introduction-policies Vault policy]&lt;br /&gt;
|-&lt;br /&gt;
| vault || Vault || {{Ops file|roles/vault/vault/files/vault.hcl}} || [https://developer.hashicorp.com/vault/docs Vault documentation]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== viperserv ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
! Unit !! Software !! Full path !! Documentation&lt;br /&gt;
|-&lt;br /&gt;
| eggdrop || Eggdrop || {{Ops file|roles/viperserv/eggdrop/files/eggdrop-bot.conf}} || [https://docs.eggheads.org/ Eggdrop documentation]&lt;br /&gt;
|-&lt;br /&gt;
| eggdrop || Eggdrop || {{Ops file|roles/viperserv/eggdrop/files/eggdrop-core.conf}} || [https://docs.eggheads.org/ Eggdrop documentation]&lt;br /&gt;
|-&lt;br /&gt;
| eggdrop || Eggdrop || {{Ops file|roles/viperserv/eggdrop/files/eggdrops-live.conf}} || [https://docs.eggheads.org/ Eggdrop documentation]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== webserver-alkane ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
! Unit !! Software !! Full path !! Documentation&lt;br /&gt;
|-&lt;br /&gt;
| alkane || Alkane || {{Ops file|roles/webserver-alkane/alkane/files/alkane.conf}} || [[Operations grimoire/Alkane|Alkane]]&lt;br /&gt;
|-&lt;br /&gt;
| alkane || Alkane || {{Ops file|roles/webserver-alkane/alkane/files/alkane.rc}} || [[Operations grimoire/Services#FreeBSD_rc|FreeBSD rc]]&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
| monitoring || PHP-FPM exporter || {{Ops file|roles/webserver-alkane/monitoring/files/rc/phpfpm_exporter.conf}} || [[Operations grimoire/Services#FreeBSD_rc|FreeBSD rc]]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/webserver-alkane/nginx/files/newsyslog/nginx.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/webserver-alkane/nginx/files/vhosts/dereckson.be/assets.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/webserver-alkane/nginx/files/vhosts/dereckson.be/hg.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/webserver-alkane/nginx/files/vhosts/dereckson.be/mediawiki.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/webserver-alkane/nginx/files/vhosts/dereckson.be/scherzo.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/webserver-alkane/nginx/files/vhosts/dereckson.be/www.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/webserver-alkane/nginx/files/vhosts/dereckson.be/www51.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/webserver-alkane/nginx/files/vhosts/dereckson.be/zed51.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/webserver-alkane/nginx/files/vhosts/espace-win.org/cosmo.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/webserver-alkane/nginx/files/vhosts/espace-win.org/grip.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/webserver-alkane/nginx/files/vhosts/espace-win.org/www.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/webserver-alkane/nginx/files/vhosts/hypership.space/www.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/webserver-alkane/nginx/files/vhosts/nasqueron.org/admin.mail.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/webserver-alkane/nginx/files/vhosts/nasqueron.org/api.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/webserver-alkane/nginx/files/vhosts/nasqueron.org/api51.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/webserver-alkane/nginx/files/vhosts/nasqueron.org/assets.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/webserver-alkane/nginx/files/vhosts/nasqueron.org/autoconfig.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/webserver-alkane/nginx/files/vhosts/nasqueron.org/daeghrefn.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/webserver-alkane/nginx/files/vhosts/nasqueron.org/docker.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/webserver-alkane/nginx/files/vhosts/nasqueron.org/docs.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/webserver-alkane/nginx/files/vhosts/nasqueron.org/drive.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/webserver-alkane/nginx/files/vhosts/nasqueron.org/ftp.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/webserver-alkane/nginx/files/vhosts/nasqueron.org/grafana.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/webserver-alkane/nginx/files/vhosts/nasqueron.org/infra.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/webserver-alkane/nginx/files/vhosts/nasqueron.org/join.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/webserver-alkane/nginx/files/vhosts/nasqueron.org/labs.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/webserver-alkane/nginx/files/vhosts/nasqueron.org/launch.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/webserver-alkane/nginx/files/vhosts/nasqueron.org/mail.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/webserver-alkane/nginx/files/vhosts/nasqueron.org/obsidian51.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/webserver-alkane/nginx/files/vhosts/nasqueron.org/packages.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/webserver-alkane/nginx/files/vhosts/nasqueron.org/rain.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/webserver-alkane/nginx/files/vhosts/nasqueron.org/tools51.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/webserver-alkane/nginx/files/vhosts/nasqueron.org/trustspace.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/webserver-alkane/nginx/files/vhosts/nasqueron.org/www.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/webserver-alkane/nginx/files/vhosts/nasqueron.org/www51.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/webserver-alkane/nginx/files/vhosts/test.ook.space/migration.mediawiki.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/webserver-alkane/nginx/files/vhosts/wolfplex.org/api.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/webserver-alkane/nginx/files/vhosts/wolfplex.org/assets.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/webserver-alkane/nginx/files/vhosts/wolfplex.org/www.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| php || PHP-FPM || {{Ops file|roles/webserver-alkane/php/files/php-fpm-pool.conf}} || [https://www.php.net/manual/en/install.fpm.configuration.php PHP-FPM documentation]&lt;br /&gt;
|-&lt;br /&gt;
| php || PHP-FPM || {{Ops file|roles/webserver-alkane/php/files/php-fpm.conf}} || [https://www.php.net/manual/en/install.fpm.configuration.php PHP-FPM documentation]&lt;br /&gt;
|-&lt;br /&gt;
| php || PHP-FPM || {{Ops file|roles/webserver-alkane/php/files/php.ini}} || [https://www.php.net/manual/en/configuration.file.php PHP configuration file]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== webserver-content ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
! Unit !! Software !! Full path !! Documentation&lt;br /&gt;
|-&lt;br /&gt;
| _generic || Environment || {{Ops file|roles/webserver-content/_generic/files/dot.env}} || [https://github.com/vlucas/phpdotenv dotenv]&lt;br /&gt;
|-&lt;br /&gt;
| org/nasqueron || Git || {{Ops file|roles/webserver-content/org/nasqueron/files/git-safe.conf}} || [https://git-scm.com/docs/git-config git-config documentation]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== webserver-core ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
! Unit !! Software !! Full path !! Documentation&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/webserver-core/nginx/files/nginx.conf}} || [https://nginx.org/en/docs/ nginx documentation]&lt;br /&gt;
|-&lt;br /&gt;
| nginx || nginx || {{Ops file|roles/webserver-core/nginx/files/nginx.rc}} || [[Operations grimoire/Services#FreeBSD_rc|FreeBSD rc]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== webserver-legacy ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
! Unit !! Software !! Full path !! Documentation&lt;br /&gt;
|-&lt;br /&gt;
| php-sites || PHP-FPM || {{Ops file|roles/webserver-legacy/php-sites/files/php-fpm-pool.conf}} || [https://www.php.net/manual/en/install.fpm.configuration.php PHP-FPM documentation]&lt;br /&gt;
|-&lt;br /&gt;
| php-sites || PHP-FPM || {{Ops file|roles/webserver-legacy/php-sites/files/php-fpm.conf}} || [https://www.php.net/manual/en/install.fpm.configuration.php PHP-FPM documentation]&lt;br /&gt;
|-&lt;br /&gt;
| php-sites || PHP-FPM || {{Ops file|roles/webserver-legacy/php-sites/files/php.ini}} || [https://www.php.net/manual/en/configuration.file.php PHP configuration file]&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Dereckson</name></author>
	</entry>
	<entry>
		<id>https://agora.nasqueron.org/index.php?title=Operations_grimoire/Services&amp;diff=2518</id>
		<title>Operations grimoire/Services</title>
		<link rel="alternate" type="text/html" href="https://agora.nasqueron.org/index.php?title=Operations_grimoire/Services&amp;diff=2518"/>
		<updated>2026-04-05T20:50:48Z</updated>

		<summary type="html">&lt;p&gt;Dereckson: /* FreeBSD rc */ Basic instructions&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Software running as daemons should be set as services to manage them at OS level a standard way.&lt;br /&gt;
&lt;br /&gt;
== Systemd, rc and runit ==&lt;br /&gt;
&lt;br /&gt;
Nasqueron infrastructure uses 3 services software:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Service management&lt;br /&gt;
|-&lt;br /&gt;
! OS !! Use case !! Software !! Commands&lt;br /&gt;
|-&lt;br /&gt;
| FreeBSD || Standard || rc || service &amp;lt;service&amp;gt; &amp;lt;command&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Linux || Standard || systemd || systemctl &amp;lt;command&amp;gt; &amp;lt;service&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Linux || Docker containers || runit || sv &amp;lt;service&amp;gt; &amp;lt;command&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Note how systemd inverts the general order by putting the command before the service.&lt;br /&gt;
&lt;br /&gt;
== Systemd ==&lt;br /&gt;
=== Services ===&lt;br /&gt;
Search for .service file in operations repository for an idea.&lt;br /&gt;
It&#039;s well documented on ArchLinux wiki and freedesktop.org site.&lt;br /&gt;
&lt;br /&gt;
References:&lt;br /&gt;
* https://www.freedesktop.org/software/systemd/man/latest/systemd.service.html&lt;br /&gt;
* https://wiki.archlinux.org/title/Systemd&lt;br /&gt;
&lt;br /&gt;
=== Timers ===&lt;br /&gt;
* Generally better to use a systemd service and a systemd timer than a crontab entry on Linux&lt;br /&gt;
* Don&#039;t forget to start the timer, see [https://devcentral.nasqueron.org/D3674#57039 this comment on D3674] for a demonstration&lt;br /&gt;
&lt;br /&gt;
=== Howto for operations repository ===&lt;br /&gt;
You can follow [https://www.dereckson.be/blog/2017/01/25/deploy-a-darkbot-or-a-simple-generic-service-with-saltstack-part-1/ this tutorial] to deploy a service on Nasqueron infrastructure, it covers the step from software deployment, configuration, user creation and a systemd service.&lt;br /&gt;
&lt;br /&gt;
== FreeBSD rc ==&lt;br /&gt;
=== Structure of a rc configuration file ===&lt;br /&gt;
Each service is configured in /etc/rc.conf.d/&amp;lt;service&amp;gt; file or by all the files in /etc/rc.conf.d/&amp;lt;service&amp;gt;/ directory.&lt;br /&gt;
&lt;br /&gt;
Those files follow [https://man.freebsd.org/cgi/man.cgi?rc.conf rc.conf syntax] and use:&lt;br /&gt;
* &amp;lt;service&amp;gt;_enable=&amp;quot;YES&amp;quot; to indicate auto start of the service&lt;br /&gt;
* various &amp;lt;service&amp;gt;_&amp;lt;key&amp;gt;=&amp;lt;value&amp;gt; per service documentation&lt;br /&gt;
&lt;br /&gt;
To know all the available options for a service the best is to read the documentation at the top of every service, located in  &lt;br /&gt;
/usr/local/etc/rc.d for applications and /etc/rc.d for the base system.&lt;br /&gt;
&lt;br /&gt;
=== Template for operations repository ===&lt;br /&gt;
If you need to add a rc service, we&#039;ve a template for the file: follow [https://devcentral.nasqueron.org/D3571 D3571 instructions]&lt;br /&gt;
&lt;br /&gt;
[[Category:Operations grimoire|Services]]&lt;/div&gt;</summary>
		<author><name>Dereckson</name></author>
	</entry>
	<entry>
		<id>https://agora.nasqueron.org/index.php?title=Operations_grimoire&amp;diff=2517</id>
		<title>Operations grimoire</title>
		<link rel="alternate" type="text/html" href="https://agora.nasqueron.org/index.php?title=Operations_grimoire&amp;diff=2517"/>
		<updated>2026-04-05T20:41:45Z</updated>

		<summary type="html">&lt;p&gt;Dereckson: /* Appendices */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:Nasqueron Operations Grimoire.jpg|thumb|320px|right|The Nasqueron operations grimoire tries to document the more arcane aspects of our complex infrastructure.]]&lt;br /&gt;
&lt;br /&gt;
Welcome to the Nasqueron operations grimoire (NOG).&lt;br /&gt;
&lt;br /&gt;
This grimoire is a reference about our infrastructure and services hosted with procedures we follow to build, maintain and deploy.&lt;br /&gt;
&lt;br /&gt;
Our infrastructure is open, mainly documented in {{repo|operations}} repository, and we actively encourage contributions from the community.&lt;br /&gt;
&lt;br /&gt;
== Infrastructure ==&lt;br /&gt;
* [[/Environments]]&lt;br /&gt;
* [[/Kubernetes]]&lt;br /&gt;
* [[/Docker engine]]&lt;br /&gt;
* [[/Salt]]&lt;br /&gt;
&lt;br /&gt;
=== OS-specific ===&lt;br /&gt;
;By OS&lt;br /&gt;
* [[/FreeBSD]]&lt;br /&gt;
* [[/RHEL]]&lt;br /&gt;
&lt;br /&gt;
;All OSes&lt;br /&gt;
* [[/NTP]]&lt;br /&gt;
* [[/Packages repository]]&lt;br /&gt;
* [[/Services]]: systemd, runit and rc&lt;br /&gt;
&lt;br /&gt;
=== Storage ===&lt;br /&gt;
* [[/ZFS]]&lt;br /&gt;
&lt;br /&gt;
=== Observability ===&lt;br /&gt;
* [[/Grafana]]&lt;br /&gt;
* [[/Logs]]&lt;br /&gt;
* [[/Prometheus]]&lt;br /&gt;
&lt;br /&gt;
=== Network ===&lt;br /&gt;
* [[/Network]]&lt;br /&gt;
* [[/DNS]]&lt;br /&gt;
* [[/Firewall]]&lt;br /&gt;
* [[/IPv6]]&lt;br /&gt;
* [https://netbox.nasqueron.org/ NetBox]&lt;br /&gt;
&lt;br /&gt;
== Services ==&lt;br /&gt;
=== Core services ===&lt;br /&gt;
; Messages queues&lt;br /&gt;
* [[/Kafka]]&lt;br /&gt;
* [[/RabbitMQ]]&lt;br /&gt;
&lt;br /&gt;
; Databases&lt;br /&gt;
* [[/MySQL]]&lt;br /&gt;
* [[/PostgreSQL]]&lt;br /&gt;
&lt;br /&gt;
; Ops&lt;br /&gt;
* [[/NetBox]]&lt;br /&gt;
&lt;br /&gt;
=== Identity management ===&lt;br /&gt;
* [[/Login]] (Auth Grove)&lt;br /&gt;
&lt;br /&gt;
=== Collaborative tools ===&lt;br /&gt;
* [[/DevCentral]] (Phabricator)&lt;br /&gt;
* [[/Etherpad]]&lt;br /&gt;
* [[/Mumble]]&lt;br /&gt;
* [[/Mastodon]] (social.nasqueron.org)&lt;br /&gt;
* [[/Openfire]] (XMPP)&lt;br /&gt;
&lt;br /&gt;
=== IRC bots ===&lt;br /&gt;
* [[/Dæghrefn]] (eggdrop)&lt;br /&gt;
* [[/Odderon]] (darkbot)&lt;br /&gt;
&lt;br /&gt;
=== Mail ===&lt;br /&gt;
* [[/Mail]]&lt;br /&gt;
* [[/Mail/DKIM]]&lt;br /&gt;
* [[/Mail/Sympa]]&lt;br /&gt;
&lt;br /&gt;
=== Web ===&lt;br /&gt;
; Common documentation for all webserver roles&lt;br /&gt;
* [[/Web/Headers]]&lt;br /&gt;
&lt;br /&gt;
; Where to host?&lt;br /&gt;
* [[/Docker engine]] for Docker containers front-end&lt;br /&gt;
* [[/Alkane]] for PHP and static sites&lt;br /&gt;
&lt;br /&gt;
; SaaS for common applications&lt;br /&gt;
* [[MediaWiki SaaS]]&lt;br /&gt;
* [[/WordPress]]&lt;br /&gt;
&lt;br /&gt;
; Other sites&lt;br /&gt;
* [[/Sites on Eglide]]&lt;br /&gt;
* [[/Sites on Ysul]] (currently migrating to Alkane)&lt;br /&gt;
&lt;br /&gt;
; Services for web applications&lt;br /&gt;
* [[/Anubis]] if you need to protect from LLM scraping traffic&lt;br /&gt;
* [[/Orbeon]] if you&#039;re in need of a form&lt;br /&gt;
&lt;br /&gt;
=== CI/CD ===&lt;br /&gt;
* [[/Broker]]&lt;br /&gt;
* [[/Docker registry]]&lt;br /&gt;
* [[/Jenkins]]&lt;br /&gt;
* [[/Notifications center]]&lt;br /&gt;
* [[/Sentry]]&lt;br /&gt;
* [[/Vault]]&lt;br /&gt;
&lt;br /&gt;
=== Shellserver ===&lt;br /&gt;
* [[/Eglide/Vault]]&lt;br /&gt;
&lt;br /&gt;
== Services configuration ==&lt;br /&gt;
&#039;&#039;This section contains general information not related to a specific service.&#039;&#039;&lt;br /&gt;
* [[/TLS certificates]] (Let&#039;s encrypt / letsencrypt)&lt;br /&gt;
&lt;br /&gt;
== Checklists ==&lt;br /&gt;
=== SSH ===&lt;br /&gt;
* [[/Recommended SSH configuration]]&lt;br /&gt;
&lt;br /&gt;
=== Infrastructure ===&lt;br /&gt;
* [[/How to add a server to the Nasqueron servers pool]]&lt;br /&gt;
* [[/How to attach a new virtual disk]]&lt;br /&gt;
* [[/Reboot checklist]]&lt;br /&gt;
&lt;br /&gt;
=== Network ===&lt;br /&gt;
* [[/Checklist router post-restart]]&lt;br /&gt;
&lt;br /&gt;
=== Docker ===&lt;br /&gt;
* [[/Restart a Docker engine]]&lt;br /&gt;
* [[/Dwellers to DevCentral]]&lt;br /&gt;
* [[/Git operations in production containers]]&lt;br /&gt;
* [[/Add a service to Docker PaaS]]&lt;br /&gt;
* [[/Docker Hub]]&lt;br /&gt;
&lt;br /&gt;
=== Salt ===&lt;br /&gt;
* [[/Operations repository]]&lt;br /&gt;
* [[/Deploy with Salt]]&lt;br /&gt;
* [[/Create and revoke user accounts on Salt servers]]&lt;br /&gt;
* [[/Provision user homefiles]]&lt;br /&gt;
&lt;br /&gt;
=== Terraform / OpenTofu ===&lt;br /&gt;
* [[/Deploy with Terraform]]&lt;br /&gt;
&lt;br /&gt;
== SIG ==&lt;br /&gt;
* [[/Onboarding]]&lt;br /&gt;
&lt;br /&gt;
== Appendices ==&lt;br /&gt;
* [[/Changelog]]&lt;br /&gt;
* [[/Contacts]]&lt;br /&gt;
* [[/Configuration files]]&lt;br /&gt;
* [[/Contribute]]&lt;br /&gt;
* [[/Decom]]&lt;br /&gt;
* [[/Evaluated products]]&lt;br /&gt;
* [[/External services]]&lt;br /&gt;
* [[/Incidents]]&lt;br /&gt;
* [[/Legacy archive]]&lt;br /&gt;
* [[/OID]]&lt;br /&gt;
* [[/Old content report]]&lt;br /&gt;
* [[/Policies]]&lt;br /&gt;
* [[/Who]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Operations grimoire|*]]&lt;br /&gt;
[[Category:Reference]]&lt;/div&gt;</summary>
		<author><name>Dereckson</name></author>
	</entry>
	<entry>
		<id>https://agora.nasqueron.org/index.php?title=Code_conventions&amp;diff=2516</id>
		<title>Code conventions</title>
		<link rel="alternate" type="text/html" href="https://agora.nasqueron.org/index.php?title=Code_conventions&amp;diff=2516"/>
		<updated>2026-04-03T22:35:38Z</updated>

		<summary type="html">&lt;p&gt;Dereckson: /* Salt */ Double quotes&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== All languages ==&lt;br /&gt;
&lt;br /&gt;
* Don&#039;t use more complicated constructs like ternary operators&lt;br /&gt;
* [http://jeroendedauw.github.io/slides/craftmanship/functions/#/1 Keep functions short and simple].&lt;br /&gt;
* Define explicitly methods visibility, as several languages have different default values (e.g. private for C# class members, public for PHP methods)&lt;br /&gt;
* Comments to document a method are written at the singular 3rd person (we seem to have moved to infinitive recently, we need to take a decision here)&lt;br /&gt;
&lt;br /&gt;
== C ==&lt;br /&gt;
If you use [http://clang.llvm.org/docs/ClangFormat.html ClangFormat], a [https://github.com/dereckson/rabbitmq-tcl/blob/master/.clang-format .clang-format file] is available.&lt;br /&gt;
&lt;br /&gt;
== JavaScript ==&lt;br /&gt;
The following conventions are used:&lt;br /&gt;
* K&amp;amp;R, 1TBS variant, including for functions&lt;br /&gt;
* 4 spaces as indent&lt;br /&gt;
* Use modern JavaScript idioms like &amp;lt;code&amp;gt;const&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;let&amp;lt;/code&amp;gt; instead of &amp;lt;code&amp;gt;var&amp;lt;/code&amp;gt;&lt;br /&gt;
* Consider to use async code for events-driven development, especially for servers&lt;br /&gt;
&lt;br /&gt;
== PHP ==&lt;br /&gt;
The following conventions are used:&lt;br /&gt;
* K&amp;amp;R, 1TBS variant, including for functions&lt;br /&gt;
* 4 spaces as indent&lt;br /&gt;
* The keywords &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;null&amp;lt;/code&amp;gt; must be in lower case.&lt;br /&gt;
* Arrays use short syntax&lt;br /&gt;
* Array elements ends with a comma&lt;br /&gt;
* Functions, methods and class names use camel case &lt;br /&gt;
&lt;br /&gt;
If you use PhpStorm or another JetBrains IDE, you can import [https://github.com/nasqueron/codestyle/blob/master/JetBrains/php-codestyle.xml JetBrains/php-codestyle.xml] from the codestyle repository as a code style (Settings or Default Settings &amp;gt; Editor &amp;gt; Code Style &amp;gt; PHP &amp;gt; click on the wheel icon &amp;gt; Import Scheme &amp;gt; Intellij IDEA codestyle XML).&lt;br /&gt;
&lt;br /&gt;
If you want to lint a project with phpcs, you can require the Composer package &amp;lt;code&amp;gt;nasqueron/codestyle&amp;lt;/code&amp;gt; and use the following &amp;lt;kbd&amp;gt;phpcs.xml&amp;lt;kbd&amp;gt; standard file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;ruleset&amp;gt;&lt;br /&gt;
    &amp;lt;rule ref=&amp;quot;vendor/nasqueron/codestyle/CodeSniffer&amp;quot; /&amp;gt;&lt;br /&gt;
    &amp;lt;file&amp;gt;.&amp;lt;/file&amp;gt;&lt;br /&gt;
    &amp;lt;exclude-pattern&amp;gt;\.git/&amp;lt;/exclude-pattern&amp;gt;&lt;br /&gt;
    &amp;lt;exclude-pattern&amp;gt;vendor/&amp;lt;/exclude-pattern&amp;gt;&lt;br /&gt;
&amp;lt;/ruleset&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Python ==&lt;br /&gt;
=== Code style ===&lt;br /&gt;
&#039;&#039;&#039;2023.&#039;&#039;&#039; We follow [https://black.readthedocs.io/en/stable/the_black_code_style/current_style.html black style], so use black utility (&amp;lt;code&amp;gt;pip install black&amp;lt;/code&amp;gt;). As such, you need to configure Flake8 to ignore rule E203.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;2015.&#039;&#039;&#039; We follow [https://www.python.org/dev/peps/pep-0008/ PEP-8].&lt;br /&gt;
&lt;br /&gt;
=== Templates ===&lt;br /&gt;
A template exists for a new Python command: [https://devcentral.nasqueron.org/source/snippets/browse/main/python/command.py python/command.py]&lt;br /&gt;
&lt;br /&gt;
In packages, empty __init__.py files can follow [https://devcentral.nasqueron.org/source/merge-dictionaries/browse/main/src/mergedictionaries/utils/__init__.py;eaf5bc2c21118454837e8148147606c19d4afff7 this example].&lt;br /&gt;
&lt;br /&gt;
=== Configuration files ===&lt;br /&gt;
Allow empty configuration files. For example, the YAML parser will return None if the file exists but is empty, we can catch that and return default instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
         with open(get_configuration_path()) as fd:&lt;br /&gt;
            return yaml.safe_load(fd) or {}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Rust ==&lt;br /&gt;
&#039;&#039;&#039;2023.&#039;&#039;&#039; Automated codestyle (black in Python, clang-format in Rust) seems preferable. As such, a style compatible with &amp;lt;code&amp;gt;rustfmt&amp;lt;/code&amp;gt; is needed to be able to format using &amp;lt;code&amp;gt;cargo fmt&amp;lt;/code&amp;gt;. You can add to your project  [https://devcentral.nasqueron.org/source/codestyle/browse/main/rust/rustfmt.toml rust/rustfmt.toml in codestyle] to configure it.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;2015.&#039;&#039;&#039; We followed &amp;quot;Rust default style&amp;quot;, described at [https://web.archive.org/web/20170320083740/http://aturon.github.io/ https://aturon.github.io/]. It&#039;s mainly a K&amp;amp;R, 1TBS variant.&lt;br /&gt;
&lt;br /&gt;
Use trailing comma for elements in every struct/impl/etc.&lt;br /&gt;
&lt;br /&gt;
=== Threads ===&lt;br /&gt;
Standard library isn&#039;t the most ergonomic for threads programming, those crate allows more efficient and legible code:&lt;br /&gt;
* [https://docs.rs/crossbeam-channel/latest/crossbeam_channel/ crossbeam_channel] for mpmc (multiple producers, multiple consumers)&lt;br /&gt;
* [https://docs.rs/parking_lot/latest/parking_lot/type.Mutex.html parking_lot] for Mutex&lt;br /&gt;
&lt;br /&gt;
== Salt ==&lt;br /&gt;
=== Style ===&lt;br /&gt;
;Whitespaces&lt;br /&gt;
* Indent with two spaces&lt;br /&gt;
* YAML lists use indented bullets&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;yaml&amp;quot;&amp;gt;&lt;br /&gt;
id:&lt;br /&gt;
  method:&lt;br /&gt;
    - somekey: value&lt;br /&gt;
    - otherkey: value&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;Quotes&lt;br /&gt;
* Use double quotes in Python, Salt and Jinja expressions&lt;br /&gt;
&lt;br /&gt;
=== Tips ===&lt;br /&gt;
&lt;br /&gt;
;Files provisioned&lt;br /&gt;
* When you ask to download a file remotely, you need a source hash, pick SHA256 as algo&lt;br /&gt;
* Each file provisioned from the Salt repository must contains an header explaining the fact, with the full path in the rOPS repo&lt;br /&gt;
&lt;br /&gt;
;BSD and Linux distros compatible states&lt;br /&gt;
* populate the map.jinja file with OS logic (e.g. `dirs` for /etc vs /usr/local/etc)&lt;br /&gt;
* when you&#039;ve a specific set of tasks to do for one OS/distro, it&#039;s acceptable to enclose it in a state by an if block&lt;br /&gt;
&lt;br /&gt;
=== Vocabulary ===&lt;br /&gt;
&lt;br /&gt;
;Domain names&lt;br /&gt;
:To refer to the fully qualified domain name sub.domain.tld, use &#039;&#039;&#039;fqdn&#039;&#039;&#039;. To split the domains in part, use &#039;&#039;&#039;domain&#039;&#039;&#039; and &#039;&#039;&#039;subdomain&#039;&#039;&#039;. This is important to understand a state without having  to refer to the associated pillar to disambig domain.&lt;br /&gt;
&lt;br /&gt;
== Shell scripts ==&lt;br /&gt;
;UNIX agnosticism:&lt;br /&gt;
* Don&#039;t assume absolute path, use &amp;lt;code&amp;gt;#!/usr/bin/env bash&amp;lt;/code&amp;gt; and not &amp;lt;code&amp;gt;#!/bin/bash&amp;lt;/code&amp;gt; (it could be elsewhere on BSD or Solaris)&lt;br /&gt;
* Use `sh` as must as possible, try to avoid &amp;lt;code&amp;gt;bash&amp;lt;/code&amp;gt;, document exceptions rationale in your commits&lt;br /&gt;
&lt;br /&gt;
;Whitespaces:&lt;br /&gt;
* One whitespace line between shebang and actual content&lt;br /&gt;
* 4 spaces as indent&lt;br /&gt;
&lt;br /&gt;
;File names:&lt;br /&gt;
* We use hyphens (-) as separators, not underscores or camelcase&lt;br /&gt;
* Filename should start by a verb if it performs an action&lt;br /&gt;
* Don&#039;t use .sh extensions when deployed as command&lt;br /&gt;
** sometimes you&#039;ll see them on Phabricator pastes&#039; titles, but it has been added there, so Phab knows shell syntax highlighting should be used&lt;br /&gt;
** &#039;&#039;&#039;Tip.&#039;&#039;&#039; You can use .sh in src/ to help linters, but then provide a Makefile to install it under correct name without extension. Same for operations repository where everything uses .sh, but when deploying with file.managed the extension is omitted&lt;br /&gt;
&lt;br /&gt;
;Templates&lt;br /&gt;
* New command: [https://devcentral.nasqueron.org/source/snippets/browse/main/shell/script.sh shell/script.sh]&lt;br /&gt;
&lt;br /&gt;
== TCL ==&lt;br /&gt;
&lt;br /&gt;
* Indent with 4 spaces, as of 2026-03-20&lt;br /&gt;
* Keep blocks visually separated&lt;br /&gt;
* Use Tcl primitives instead of manual parsing for strings: split, lindex, lrange, join&lt;br /&gt;
* Avoid regex unless necessary&lt;br /&gt;
* List expansion {*} instead of eval&lt;br /&gt;
&lt;br /&gt;
; ViperServ development&lt;br /&gt;
* If you build a full new system, all procedures must be defined in a namespace&lt;br /&gt;
* Use fully-qualified names (::namespace::proc) for procedure definitions and cross-namespace calls&lt;br /&gt;
* Separate low-level request logic from API-specific methods&lt;br /&gt;
&lt;br /&gt;
== Makefile ==&lt;br /&gt;
UNIX agnosticism:&lt;br /&gt;
* Test your makefile against BSD make, and document in README.md to use GNU Makefile (gmake) when it&#039;s not convenient to keep compatibility&lt;br /&gt;
&lt;br /&gt;
Presentation:&lt;br /&gt;
* Create a block with the general targets, then sections with your targets organized by categories/goals/parts&lt;br /&gt;
&lt;br /&gt;
Tip:&lt;br /&gt;
* It&#039;s possible to provision BSDmakefile and GNUmakefile when UNIX agnosticism doesn&#039;t work.&lt;br /&gt;
&lt;br /&gt;
== Structured data formats (YAML, JSON, XML) ==&lt;br /&gt;
The number of spaces depend if the format is usually heavily hierarchized or not:&lt;br /&gt;
&lt;br /&gt;
* 2 spaces for JSON and YAML&lt;br /&gt;
* 4 spaces for XML, TOML and other configuration files&lt;br /&gt;
&lt;br /&gt;
== Utilities ==&lt;br /&gt;
&lt;br /&gt;
The https://github.com/nasqueron/codestyle repository contains resource to help to respect code convention, like a phpcs ruleset, a configuration ready for PhpStorm, IntelliJ and other JetBrains editors, or a clang-format configuration file.&lt;br /&gt;
&lt;br /&gt;
== Troubleshoot ==&lt;br /&gt;
=== Fix indent issues ===&lt;br /&gt;
The &amp;lt;code&amp;gt;expand&amp;lt;/code&amp;gt; utility converts tabs into spaces, while &amp;lt;code&amp;gt;unexpand&amp;lt;/code&amp;gt; convert spaces into tabs.&lt;br /&gt;
&lt;br /&gt;
Switch a file from tab indent to 4 spaces indent:&lt;br /&gt;
&lt;br /&gt;
    $ expand -t 4 foo.sh &amp;gt; a&lt;br /&gt;
    $ cat a &amp;gt; foo.sh&lt;br /&gt;
    $ rm a&lt;br /&gt;
&lt;br /&gt;
(Avoid &amp;lt;code&amp;gt;mv&amp;lt;/code&amp;gt; for shell scripts as your foo.sh has probably a 755 chmod, and a will probably have a 644 chmod, assuming 022 as umask)&lt;br /&gt;
&lt;br /&gt;
Switch a file indent with 2 spaces to 4 spaces:&lt;br /&gt;
&lt;br /&gt;
    $ unexpand -t 2 JetBrains/php-codestyle.xml &amp;gt; a&lt;br /&gt;
    $ expand -t 4 a &amp;gt; JetBrains/php-codestyle.xml&lt;br /&gt;
&lt;br /&gt;
This last technique can be used in batch [https://gist.github.com/dereckson/80a746b408c0cf0b688a09db31d5c881 with this reindent script]:&lt;br /&gt;
&lt;br /&gt;
    $ git ls-files | xargs -n1 reindent 2 4 &lt;br /&gt;
&lt;br /&gt;
[[Category:Reference]]&lt;br /&gt;
[[Category:Contributor guide]]&lt;/div&gt;</summary>
		<author><name>Dereckson</name></author>
	</entry>
	<entry>
		<id>https://agora.nasqueron.org/index.php?title=WindRiver&amp;diff=2515</id>
		<title>WindRiver</title>
		<link rel="alternate" type="text/html" href="https://agora.nasqueron.org/index.php?title=WindRiver&amp;diff=2515"/>
		<updated>2026-04-03T17:19:51Z</updated>

		<summary type="html">&lt;p&gt;Dereckson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;WindRiver is an FreeBSD 14 bare metal server for Nasqueron general-purpose development.&lt;br /&gt;
&lt;br /&gt;
It supersedes [[Ysul]].&lt;br /&gt;
&lt;br /&gt;
Documentation: [[Devserver reference]]&lt;br /&gt;
&lt;br /&gt;
== Basic information ==&lt;br /&gt;
* &#039;&#039;&#039;IP:&#039;&#039;&#039;&lt;br /&gt;
** 195.154.30.15 &amp;lt;strike&amp;gt;51.159.17.168 since 2023-06-14. Previously 51.159.18.59.&amp;lt;/strike&amp;gt;&lt;br /&gt;
** 2a02:578:4f0d:0:30d0:7b22:6cde:a52e (native, still to migrate)&lt;br /&gt;
** 2001:bc8:6005:5:aa1e:84ff:fef3:5d9c (future through HE)&lt;br /&gt;
* &#039;&#039;&#039;Hostname:&#039;&#039;&#039; windriver.nasqueron.org&lt;br /&gt;
* &#039;&#039;&#039;Homepage:&#039;&#039;&#039; https://windriver.nasqueron.org/&lt;br /&gt;
* &#039;&#039;&#039;Configuration:&#039;&#039;&#039; &amp;lt;strike&amp;gt;64 Gb RAM, Xeon E3 1240 V6, 2x 500 GB SSD (&amp;quot;Pro-6-S&amp;quot;)&amp;lt;/strike&amp;gt; 96 Gb. RAM, Xeon E5-1650 v3, 3x 500 GB SSD (&amp;quot;Pro-4-L&amp;quot;)&lt;br /&gt;
* &#039;&#039;&#039;ISP:&#039;&#039;&#039; [http://www.online.net Online] (FR)&lt;br /&gt;
* &#039;&#039;&#039;Network:&#039;&#039;&#039; Illiad (FR)&lt;br /&gt;
* &#039;&#039;&#039;Policy:&#039;&#039;&#039; Access for any Nasqueron project and for infrastructure operations task.&lt;br /&gt;
* &#039;&#039;&#039;Started:&#039;&#039;&#039; 2019-11-21&lt;br /&gt;
&lt;br /&gt;
== Ports ==&lt;br /&gt;
&lt;br /&gt;
Ports for services managed automatically through Salt are available on {{Ops file|PORTS}}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Reserved ports - IRC server range&lt;br /&gt;
|-&lt;br /&gt;
! Port !! User account !! Description&lt;br /&gt;
|-&lt;br /&gt;
| 6901 || dereckson || irssi proxy&lt;br /&gt;
|-&lt;br /&gt;
| 6902 || dereckson || irssi proxy&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Troubleshoot ==&lt;br /&gt;
&lt;br /&gt;
=== To check after reboot ===&lt;br /&gt;
&lt;br /&gt;
* Network&lt;br /&gt;
** IPv4 - ICANN&lt;br /&gt;
** IPv6 - main + viperserv alias&lt;br /&gt;
** IPv6 - can we reach something with IPv6&lt;br /&gt;
** IPv4 - Drake: tunnel + route + ping any server&lt;br /&gt;
* Services&lt;br /&gt;
** Alkane HTTP server&lt;br /&gt;
** API exec HTTP server&lt;br /&gt;
** Bitlbee&lt;br /&gt;
** Eggdrops: Dæghrefn + Wearg&lt;br /&gt;
** Grafana&lt;br /&gt;
** MariaDB&lt;br /&gt;
** NetBox&lt;br /&gt;
** nginx&lt;br /&gt;
** Node exporter for Prometheus&lt;br /&gt;
** oidentd&lt;br /&gt;
** php-fpm&lt;br /&gt;
** PostgreSQL&lt;br /&gt;
** Prometheus&lt;br /&gt;
** Redis&lt;br /&gt;
** Salt minion&lt;br /&gt;
** SSH server&lt;br /&gt;
* Vault connectivity&lt;/div&gt;</summary>
		<author><name>Dereckson</name></author>
	</entry>
	<entry>
		<id>https://agora.nasqueron.org/index.php?title=How_to_communicate&amp;diff=2495</id>
		<title>How to communicate</title>
		<link rel="alternate" type="text/html" href="https://agora.nasqueron.org/index.php?title=How_to_communicate&amp;diff=2495"/>
		<updated>2026-03-24T17:13:32Z</updated>

		<summary type="html">&lt;p&gt;Dereckson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page shows tools and best practices to communicate efficiently about code changes or operations activities.&lt;br /&gt;
&lt;br /&gt;
== Ways of communication ==&lt;br /&gt;
&lt;br /&gt;
=== Discussion spaces ===&lt;br /&gt;
Our primary discussion spaces are IRC, DevCentral and here on Agora:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Primary discussion spaces&lt;br /&gt;
|-&lt;br /&gt;
! Space !! How to join !! Scope&lt;br /&gt;
|-&lt;br /&gt;
| [[IRC]] || [https://libera.chat/ Libera.chat] #nasqueron-ops || Discussions about servers, infrastructure, operations, access.&amp;lt;br&amp;gt;Also, as it&#039;s currently our main discussion space, you&#039;re welcome to hangout there if you want to chat with fellow nasquenautes.&lt;br /&gt;
|-&lt;br /&gt;
| DevCentral || Browse https://devcentral.nasqueron.org || Tasks, project management, status update, sprints, ideas&lt;br /&gt;
|-&lt;br /&gt;
| Agora || You&#039;re here! [https://forms.nasqueron.org/nasqueron-requests/agora-account/new Request an account] || Documentation, projects, idea, personal notes&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
We also use Jitsi as video-conference platform and some members currently use Discord to organize their contributions:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Known discussion spaces&lt;br /&gt;
|-&lt;br /&gt;
! Space !! How to join !! Scope&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
| Discord || https://discord.gg/DZQK8Dd8Xd || ServPulse&lt;br /&gt;
|-&lt;br /&gt;
| Jitsi || https://meet.jit.si/nasqueron || Any topic.&amp;lt;br&amp;gt;Tip: If you&#039;re first on the meeting, you can login through GitHub to open it.&lt;br /&gt;
|}&lt;br /&gt;
=== By project ===&lt;br /&gt;
* Nasqueron Operations SIG uses IRC: Libera.chat #nasqueron-ops&lt;br /&gt;
* Eli and Amine work on Discord for [[ServPulse]]&lt;br /&gt;
&lt;br /&gt;
=== Tips for audio and video meeting ===&lt;br /&gt;
A headset can help a lot to get clear communication, without echo or reverb. When you don&#039;t have it, try to mute yourself when you don&#039;t speak (Jitsi) or enable push-to-talk feature (Discord).&lt;br /&gt;
&lt;br /&gt;
Dereckson has a spare USB headset from Sennheiser if you need one.&lt;br /&gt;
&lt;br /&gt;
== Share logs, screenshots ==&lt;br /&gt;
;Core recommandations&lt;br /&gt;
* DO: use appropriate tools to share information through a short link&lt;br /&gt;
* DON&#039;T: use screenshots to share text, text must be shared as text&lt;br /&gt;
* DON&#039;T: copy/paste full logs in chat&lt;br /&gt;
* DON&#039;T: share logs with privacy data / PII, in that case give a reference to go to that log&lt;br /&gt;
&lt;br /&gt;
;Tools to use&lt;br /&gt;
* To share directly the ouput of a command&lt;br /&gt;
** [https://termbin.com/ Termbin]: &amp;lt;code&amp;gt;command | nc termbin.com 9999&amp;lt;/code&amp;gt;&lt;br /&gt;
** Arcanist to publish to DevCentral: &amp;lt;code&amp;gt;command | arc paste --&amp;lt;/code&amp;gt;&lt;br /&gt;
* To share clipboard content&lt;br /&gt;
** https://dpaste.com/&lt;br /&gt;
** DevCentral: [https://devcentral.nasqueron.org/paste/edit/form/default/ create paste], that gives a reference to put in other objects (tasks, differential), use &amp;lt;code&amp;gt;{P100}&amp;lt;/code&amp;gt; for direct inclusion or &amp;lt;code&amp;gt;P100&amp;lt;/code&amp;gt; for link&lt;br /&gt;
* To share source code&lt;br /&gt;
** Pastebin are totally appropriated too&lt;br /&gt;
** You can also use GitHub Gist: https://gist.github.com - they can be secret or publicly available&lt;br /&gt;
** You can send a pull request to the repository for proof of concept&lt;br /&gt;
** If you want to discuss a pull request against an upstream repository, DevCentral allows &amp;quot;free&amp;quot; diff not linked to any repo too: [https://devcentral.nasqueron.org/differential/diff/create/ diff/create]&lt;br /&gt;
&lt;br /&gt;
;Too many tools! I&#039;m lost&lt;br /&gt;
It can require some practice to be able to pick among the most appropriate tool, so you can start with:&lt;br /&gt;
* Command output -&amp;gt; &amp;lt;code&amp;gt;command | nc termbin.com 9999&amp;lt;/code&amp;gt;&lt;br /&gt;
* Anything else&lt;br /&gt;
** Ephemeral -&amp;gt; https://dpaste.com/&lt;br /&gt;
** To save and discuss in tasks -&amp;gt; https://devcentral.nasqueron.org/paste/edit/form/default/&lt;br /&gt;
&lt;br /&gt;
[[Category:Contributor guide]]&lt;br /&gt;
[[Category:Reference]]&lt;/div&gt;</summary>
		<author><name>Dereckson</name></author>
	</entry>
	<entry>
		<id>https://agora.nasqueron.org/index.php?title=Operations_grimoire/Deploy_with_Terraform&amp;diff=2494</id>
		<title>Operations grimoire/Deploy with Terraform</title>
		<link rel="alternate" type="text/html" href="https://agora.nasqueron.org/index.php?title=Operations_grimoire/Deploy_with_Terraform&amp;diff=2494"/>
		<updated>2026-03-22T23:51:29Z</updated>

		<summary type="html">&lt;p&gt;Dereckson: /* Propagate secrets (DRP) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Where to work? ==&lt;br /&gt;
We deploy from [[Complector]] using &amp;lt;code&amp;gt;/opt/salt/nasqueron-operations&amp;lt;/code&amp;gt; as our local copy of rOPS, authoritative for both Salt and Terraform&lt;br /&gt;
&lt;br /&gt;
You need to belong to the &amp;lt;code&amp;gt;ops&amp;lt;/code&amp;gt; group to be able to have access and have write-rights on the repository&lt;br /&gt;
&lt;br /&gt;
It&#039;s important to work from there to save a shared Terraform state.&lt;br /&gt;
&lt;br /&gt;
== Specific deployment notes ==&lt;br /&gt;
=== Vault / OpenBao ===&lt;br /&gt;
==== General notes ====&lt;br /&gt;
;OpenTofu support&lt;br /&gt;
As of 2026-02-07, the Vault provider isn&#039;t compiled for FreeBSD. You need to use Terraform instead.&lt;br /&gt;
&lt;br /&gt;
;Vault&lt;br /&gt;
You need a Vault token to allow the provider to connect.&lt;br /&gt;
&lt;br /&gt;
You also need to set VAULT_ADDR to https://172.27.27.7:8200 as Vault doesn&#039;t listen on 127.0.0.1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;shell&amp;quot;&amp;gt;&lt;br /&gt;
$ export VAULT_ADDR=https://172.27.27.7:8200&lt;br /&gt;
$ sudo /opt/salt/nasqueron-operations/utils/vault/issue-admin-token.py &amp;gt; ~/.vault-token&lt;br /&gt;
    &lt;br /&gt;
$ cd /opt/salt/nasqueron-operations/terraform/openbao&lt;br /&gt;
$ terraform init # if you&#039;ve a new entry requiring a module, it needs to be installed&lt;br /&gt;
$ terraform plan&lt;br /&gt;
$ terraform apply&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It could be interesting to maintain an alternative policy to admin for the Terraform provider, restricted to the current actions. Note benefits would be limited as those include policies management.&lt;br /&gt;
&lt;br /&gt;
==== Propagate secrets (DRP) ====&lt;br /&gt;
;No automatic secret rotation&lt;br /&gt;
Secrets rotation is disabled with a lifecycle management &amp;lt;code&amp;gt;ignore_changes = [ secret_id, ]&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
To rotate a secret, it needs first to be destroyed from terraform state:&lt;br /&gt;
&amp;lt;code&amp;gt;terraform destroy -target=module.viperserv_approle.vault_approle_auth_backend_role_secret_id.this&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;Full procedure &lt;br /&gt;
Once the AppRole have been created in Vault, they need to be provisioned to the relevant configuration files.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;shell&amp;quot;&amp;gt;&lt;br /&gt;
$ cd /opt/salt/nasqueron-operations/terraform/openbao&lt;br /&gt;
$ terraform init # if you&#039;ve a new entry requiring a module, it needs to be installed&lt;br /&gt;
$ terraform plan&lt;br /&gt;
$ terraform apply&lt;br /&gt;
&lt;br /&gt;
$ cd /opt/salt/nasqueron-operations&lt;br /&gt;
$ salt windriver state.sls_id /usr/local/etc/secrets/rhyne-wyse.yaml roles/reports/rhyne-wyse/config&lt;br /&gt;
$ salt windriver state.sls_id /srv/viperserv/.credentials roles/viperserv/eggdrop/config&lt;br /&gt;
# Missing for router&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;alert&amp;quot;&amp;gt;Important. Each time you&#039;ll reprovision the secrets, they will change.&lt;br /&gt;
&lt;br /&gt;
Don&#039;t forget to always apply this full procedure.&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Table of Terraform states ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Terraform and OpenBao states&lt;br /&gt;
|-&lt;br /&gt;
! Configuration !! State back-end !! Path !! Software to use&lt;br /&gt;
|-&lt;br /&gt;
| openbao || On disk || /opt/salt/nasqueron-operations/terraform/openbao/terraform.tfstate || Terraform&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
On disk paths are stored in Complector.&lt;br /&gt;
&lt;br /&gt;
== Troubleshoot ==&lt;br /&gt;
=== Error: Module not installed ===&lt;br /&gt;
&lt;br /&gt;
You need to run &amp;lt;code&amp;gt;tofu init&amp;lt;/code&amp;gt; to prepare for any new provider.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;shell&amp;quot;&amp;gt;&lt;br /&gt;
$ tofu plan&lt;br /&gt;
&lt;br /&gt;
│ Error: Module not installed&lt;br /&gt;
│ &lt;br /&gt;
│   on rhyne_wyse.tf line 23:&lt;br /&gt;
│   23: module &amp;quot;rhyne_wyse_approle&amp;quot; {&lt;br /&gt;
│ &lt;br /&gt;
│ This module is not yet installed. Run &amp;quot;tofu init&amp;quot; to install all modules required by this configuration.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Error: Incompatible provider version ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;shell&amp;quot;&amp;gt;&lt;br /&gt;
$ tofu init&lt;br /&gt;
&lt;br /&gt;
Initializing the backend...&lt;br /&gt;
Initializing modules...&lt;br /&gt;
- rhyne_wyse_approle in modules/app_credentials&lt;br /&gt;
&lt;br /&gt;
Initializing provider plugins...&lt;br /&gt;
- Finding hashicorp/vault versions matching &amp;quot;5.3.0&amp;quot;...&lt;br /&gt;
╷&lt;br /&gt;
│ Error: Incompatible provider version&lt;br /&gt;
│ &lt;br /&gt;
│ Provider registry.opentofu.org/hashicorp/vault v5.3.0 does not have a package available for your current platform, freebsd_amd64.&lt;br /&gt;
│ &lt;br /&gt;
│ Provider releases are separate from OpenTofu CLI releases, so not all providers are available for all platforms. Other versions of this provider may have different platforms supported.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On OpenTofu, some modules are only compiled for Linux, not for FreeBSD.&lt;br /&gt;
Switch to Terraform pending a solution to help the OpenTofu builds.&lt;br /&gt;
&lt;br /&gt;
[[Category:Operations grimoire]]&lt;br /&gt;
[[Category:Terraform]]&lt;/div&gt;</summary>
		<author><name>Dereckson</name></author>
	</entry>
	<entry>
		<id>https://agora.nasqueron.org/index.php?title=MediaWiki:Common.css&amp;diff=2493</id>
		<title>MediaWiki:Common.css</title>
		<link rel="alternate" type="text/html" href="https://agora.nasqueron.org/index.php?title=MediaWiki:Common.css&amp;diff=2493"/>
		<updated>2026-03-22T23:50:38Z</updated>

		<summary type="html">&lt;p&gt;Dereckson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* Source code */&lt;br /&gt;
&lt;br /&gt;
code, tt, kbd, pre, samp {&lt;br /&gt;
	font-size: 0.9em !important;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Call for actions button  */&lt;br /&gt;
&lt;br /&gt;
.btn {&lt;br /&gt;
	-webkit-border-radius: 6;&lt;br /&gt;
	-moz-border-radius: 6;&lt;br /&gt;
	border-radius: 6px;&lt;br /&gt;
	color: #ffffff;&lt;br /&gt;
	font-size: 1.4em;&lt;br /&gt;
	background: #4d7b94;&lt;br /&gt;
	padding: 10px 20px 10px 20px;&lt;br /&gt;
	text-decoration: none;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.btn a, .btn a:hover, .btn a:visited {&lt;br /&gt;
	color: white !important;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.btn:hover {&lt;br /&gt;
	background: #6caacc;&lt;br /&gt;
	text-decoration: none;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Inline code  */&lt;br /&gt;
&lt;br /&gt;
.inline-code, .inline-code div,  .inline-code pre {&lt;br /&gt;
	display: inline-table;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
    Banners&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
.alert {&lt;br /&gt;
  background: #d32f2f;&lt;br /&gt;
  color: #fff;&lt;br /&gt;
  padding: 0.75rem 1rem;&lt;br /&gt;
  border-radius: 4px;&lt;br /&gt;
  font-weight: 600;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
    Colors from 2017 palette&lt;br /&gt;
    &lt;br /&gt;
    See https://devcentral.nasqueron.org/M11 or [[Design/2017 colors]]&lt;br /&gt;
 */&lt;br /&gt;
 &lt;br /&gt;
.color-magnetic-one {&lt;br /&gt;
	/* Cyberspace gray */&lt;br /&gt;
	color: #44484D;&lt;br /&gt;
}&lt;br /&gt;
.color-magnetic-two {&lt;br /&gt;
	/* Anchors Aweigh blue */&lt;br /&gt;
	color: #2B3441;&lt;br /&gt;
}&lt;br /&gt;
.color-magnetic-three {&lt;br /&gt;
	/* Niagara blue — Pantone 17-4123 */&lt;br /&gt;
	color: #5587A2; &lt;br /&gt;
}&lt;br /&gt;
.color-magnetic-four {&lt;br /&gt;
	/* Primrose yellow — Pantone 13-0755 */&lt;br /&gt;
	color: #F6D258;&lt;br /&gt;
}&lt;br /&gt;
.color-magnetic-five {&lt;br /&gt;
	/* Green from http://www.elledecor.com/design-decorate/color/g3175/color-trends/ */&lt;br /&gt;
	color: #67947D;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
    Responsive blocks.&lt;br /&gt;
 */&lt;br /&gt;
 &lt;br /&gt;
.block {&lt;br /&gt;
	margin: 0 0;&lt;br /&gt;
	padding: 5vh 5vw;&lt;br /&gt;
	&lt;br /&gt;
	border: #808080 solid 5px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.block-col {&lt;br /&gt;
	position: relative;&lt;br /&gt;
	display:inline;&lt;br /&gt;
	float: left;&lt;br /&gt;
	margin-right: 1em;&lt;br /&gt;
	padding: 1vw;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.block-col-quarter {&lt;br /&gt;
	width: 20%;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.block-col-half {&lt;br /&gt;
	width: 40%;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.user-block {&lt;br /&gt;
	min-height: 50vh;&lt;br /&gt;
	background-color: #44484D;&lt;br /&gt;
	color: white;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.user-block dt {&lt;br /&gt;
    color: #67947D;&lt;br /&gt;
    font-family: &#039;Segoe UI&#039;, &#039;Segoe UI Emoji&#039;, &#039;Segoe UI Symbol&#039;, &#039;Lato&#039;, &#039;Liberation Sans&#039;, &#039;Noto Sans&#039;, &#039;Helvetica Neue&#039;, &#039;Helvetica&#039;, sans-serif;&lt;br /&gt;
    font-size: 1.375em;&lt;br /&gt;
    margin-bottom: 1em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.user-block a {&lt;br /&gt;
    color: #F6D258 !important;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
	Variable Grid System.&lt;br /&gt;
	Learn more ~ http://www.spry-soft.com/grids/&lt;br /&gt;
	Based on 960 Grid System - http://960.gs/&lt;br /&gt;
&lt;br /&gt;
	Licensed under GPL and MIT.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/* Containers&lt;br /&gt;
----------------------------------------------------------------------------------------------------*/&lt;br /&gt;
.container_12 {&lt;br /&gt;
	margin-left: auto;&lt;br /&gt;
	margin-right: auto;&lt;br /&gt;
	width: 960px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Grid &amp;gt;&amp;gt; Global&lt;br /&gt;
----------------------------------------------------------------------------------------------------*/&lt;br /&gt;
&lt;br /&gt;
.grid_1,&lt;br /&gt;
.grid_2,&lt;br /&gt;
.grid_3,&lt;br /&gt;
.grid_4,&lt;br /&gt;
.grid_5,&lt;br /&gt;
.grid_6,&lt;br /&gt;
.grid_7,&lt;br /&gt;
.grid_8,&lt;br /&gt;
.grid_9,&lt;br /&gt;
.grid_10,&lt;br /&gt;
.grid_11,&lt;br /&gt;
.grid_12 {&lt;br /&gt;
	display:inline;&lt;br /&gt;
	float: left;&lt;br /&gt;
	position: relative;&lt;br /&gt;
	margin-left: 10px;&lt;br /&gt;
	margin-right: 10px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Grid &amp;gt;&amp;gt; Children (Alpha ~ First, Omega ~ Last)&lt;br /&gt;
----------------------------------------------------------------------------------------------------*/&lt;br /&gt;
&lt;br /&gt;
.alpha {&lt;br /&gt;
	margin-left: 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.omega {&lt;br /&gt;
	margin-right: 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Grid &amp;gt;&amp;gt; 12 Columns&lt;br /&gt;
----------------------------------------------------------------------------------------------------*/&lt;br /&gt;
&lt;br /&gt;
.container_12 .grid_1 {&lt;br /&gt;
	width:60px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.container_12 .grid_2 {&lt;br /&gt;
	width:140px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.container_12 .grid_3 {&lt;br /&gt;
	width:220px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.container_12 .grid_4 {&lt;br /&gt;
	width:300px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.container_12 .grid_5 {&lt;br /&gt;
	width:380px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.container_12 .grid_6 {&lt;br /&gt;
	width:460px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.container_12 .grid_7 {&lt;br /&gt;
	width:540px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.container_12 .grid_8 {&lt;br /&gt;
	width:620px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.container_12 .grid_9 {&lt;br /&gt;
	width:700px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.container_12 .grid_10 {&lt;br /&gt;
	width:780px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.container_12 .grid_11 {&lt;br /&gt;
	width:860px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.container_12 .grid_12 {&lt;br /&gt;
	width:940px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/* Prefix Extra Space &amp;gt;&amp;gt; 12 Columns&lt;br /&gt;
----------------------------------------------------------------------------------------------------*/&lt;br /&gt;
&lt;br /&gt;
.container_12 .prefix_1 {&lt;br /&gt;
	padding-left:80px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.container_12 .prefix_2 {&lt;br /&gt;
	padding-left:160px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.container_12 .prefix_3 {&lt;br /&gt;
	padding-left:240px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.container_12 .prefix_4 {&lt;br /&gt;
	padding-left:320px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.container_12 .prefix_5 {&lt;br /&gt;
	padding-left:400px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.container_12 .prefix_6 {&lt;br /&gt;
	padding-left:480px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.container_12 .prefix_7 {&lt;br /&gt;
	padding-left:560px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.container_12 .prefix_8 {&lt;br /&gt;
	padding-left:640px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.container_12 .prefix_9 {&lt;br /&gt;
	padding-left:720px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.container_12 .prefix_10 {&lt;br /&gt;
	padding-left:800px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.container_12 .prefix_11 {&lt;br /&gt;
	padding-left:880px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/* Suffix Extra Space &amp;gt;&amp;gt; 12 Columns&lt;br /&gt;
----------------------------------------------------------------------------------------------------*/&lt;br /&gt;
&lt;br /&gt;
.container_12 .suffix_1 {&lt;br /&gt;
	padding-right:80px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.container_12 .suffix_2 {&lt;br /&gt;
	padding-right:160px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.container_12 .suffix_3 {&lt;br /&gt;
	padding-right:240px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.container_12 .suffix_4 {&lt;br /&gt;
	padding-right:320px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.container_12 .suffix_5 {&lt;br /&gt;
	padding-right:400px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.container_12 .suffix_6 {&lt;br /&gt;
	padding-right:480px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.container_12 .suffix_7 {&lt;br /&gt;
	padding-right:560px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.container_12 .suffix_8 {&lt;br /&gt;
	padding-right:640px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.container_12 .suffix_9 {&lt;br /&gt;
	padding-right:720px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.container_12 .suffix_10 {&lt;br /&gt;
	padding-right:800px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.container_12 .suffix_11 {&lt;br /&gt;
	padding-right:880px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/* Push Space &amp;gt;&amp;gt; 12 Columns&lt;br /&gt;
----------------------------------------------------------------------------------------------------*/&lt;br /&gt;
&lt;br /&gt;
.container_12 .push_1 {&lt;br /&gt;
	left:80px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.container_12 .push_2 {&lt;br /&gt;
	left:160px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.container_12 .push_3 {&lt;br /&gt;
	left:240px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.container_12 .push_4 {&lt;br /&gt;
	left:320px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.container_12 .push_5 {&lt;br /&gt;
	left:400px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.container_12 .push_6 {&lt;br /&gt;
	left:480px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.container_12 .push_7 {&lt;br /&gt;
	left:560px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.container_12 .push_8 {&lt;br /&gt;
	left:640px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.container_12 .push_9 {&lt;br /&gt;
	left:720px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.container_12 .push_10 {&lt;br /&gt;
	left:800px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.container_12 .push_11 {&lt;br /&gt;
	left:880px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/* Pull Space &amp;gt;&amp;gt; 12 Columns&lt;br /&gt;
----------------------------------------------------------------------------------------------------*/&lt;br /&gt;
&lt;br /&gt;
.container_12 .pull_1 {&lt;br /&gt;
	left:-80px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.container_12 .pull_2 {&lt;br /&gt;
	left:-160px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.container_12 .pull_3 {&lt;br /&gt;
	left:-240px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.container_12 .pull_4 {&lt;br /&gt;
	left:-320px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.container_12 .pull_5 {&lt;br /&gt;
	left:-400px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.container_12 .pull_6 {&lt;br /&gt;
	left:-480px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.container_12 .pull_7 {&lt;br /&gt;
	left:-560px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.container_12 .pull_8 {&lt;br /&gt;
	left:-640px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.container_12 .pull_9 {&lt;br /&gt;
	left:-720px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.container_12 .pull_10 {&lt;br /&gt;
	left:-800px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.container_12 .pull_11 {&lt;br /&gt;
	left:-880px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/* Clear Floated Elements&lt;br /&gt;
----------------------------------------------------------------------------------------------------*/&lt;br /&gt;
&lt;br /&gt;
/* http://sonspring.com/journal/clearing-floats */&lt;br /&gt;
&lt;br /&gt;
.clear {&lt;br /&gt;
	clear: both;&lt;br /&gt;
	display: block;&lt;br /&gt;
	overflow: hidden;&lt;br /&gt;
	visibility: hidden;&lt;br /&gt;
	width: 0;&lt;br /&gt;
	height: 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* http://perishablepress.com/press/2008/02/05/lessons-learned-concerning-the-clearfix-css-hack */&lt;br /&gt;
&lt;br /&gt;
.clearfix:after {&lt;br /&gt;
	clear: both;&lt;br /&gt;
	content: &#039; &#039;;&lt;br /&gt;
	display: block;&lt;br /&gt;
	font-size: 0;&lt;br /&gt;
	line-height: 0;&lt;br /&gt;
	visibility: hidden;&lt;br /&gt;
	width: 0;&lt;br /&gt;
	height: 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.clearfix {&lt;br /&gt;
	display: inline-block;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
* html .clearfix {&lt;br /&gt;
	height: 1%;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.clearfix {&lt;br /&gt;
	display: block;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Dereckson</name></author>
	</entry>
	<entry>
		<id>https://agora.nasqueron.org/index.php?title=Operations_grimoire/Deploy_with_Terraform&amp;diff=2492</id>
		<title>Operations grimoire/Deploy with Terraform</title>
		<link rel="alternate" type="text/html" href="https://agora.nasqueron.org/index.php?title=Operations_grimoire/Deploy_with_Terraform&amp;diff=2492"/>
		<updated>2026-03-22T23:18:13Z</updated>

		<summary type="html">&lt;p&gt;Dereckson: /* Propagate secrets (DRP) */ # Missing for router&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Where to work? ==&lt;br /&gt;
We deploy from [[Complector]] using &amp;lt;code&amp;gt;/opt/salt/nasqueron-operations&amp;lt;/code&amp;gt; as our local copy of rOPS, authoritative for both Salt and Terraform&lt;br /&gt;
&lt;br /&gt;
You need to belong to the &amp;lt;code&amp;gt;ops&amp;lt;/code&amp;gt; group to be able to have access and have write-rights on the repository&lt;br /&gt;
&lt;br /&gt;
It&#039;s important to work from there to save a shared Terraform state.&lt;br /&gt;
&lt;br /&gt;
== Specific deployment notes ==&lt;br /&gt;
=== Vault / OpenBao ===&lt;br /&gt;
==== General notes ====&lt;br /&gt;
;OpenTofu support&lt;br /&gt;
As of 2026-02-07, the Vault provider isn&#039;t compiled for FreeBSD. You need to use Terraform instead.&lt;br /&gt;
&lt;br /&gt;
;Vault&lt;br /&gt;
You need a Vault token to allow the provider to connect.&lt;br /&gt;
&lt;br /&gt;
You also need to set VAULT_ADDR to https://172.27.27.7:8200 as Vault doesn&#039;t listen on 127.0.0.1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;shell&amp;quot;&amp;gt;&lt;br /&gt;
$ export VAULT_ADDR=https://172.27.27.7:8200&lt;br /&gt;
$ sudo /opt/salt/nasqueron-operations/utils/vault/issue-admin-token.py &amp;gt; ~/.vault-token&lt;br /&gt;
    &lt;br /&gt;
$ cd /opt/salt/nasqueron-operations/terraform/openbao&lt;br /&gt;
$ terraform init # if you&#039;ve a new entry requiring a module, it needs to be installed&lt;br /&gt;
$ terraform plan&lt;br /&gt;
$ terraform apply&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It could be interesting to maintain an alternative policy to admin for the Terraform provider, restricted to the current actions. Note benefits would be limited as those include policies management.&lt;br /&gt;
&lt;br /&gt;
==== Propagate secrets (DRP) ====&lt;br /&gt;
;No automatic secret rotation&lt;br /&gt;
Secrets rotation is disabled with a lifecycle management &amp;lt;code&amp;gt;ignore_changes = [ secret_id, ]&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
To rotate a secret, it needs first to be destroyed from terraform state:&lt;br /&gt;
&amp;lt;code&amp;gt;terraform destroy -target=module.viperserv_approle.vault_approle_auth_backend_role_secret_id.this&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;Full procedure &lt;br /&gt;
Once the AppRole have been created in Vault, they need to be provisioned to the relevant configuration files.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;shell&amp;quot;&amp;gt;&lt;br /&gt;
$ cd /opt/salt/nasqueron-operations/terraform/openbao&lt;br /&gt;
$ terraform init # if you&#039;ve a new entry requiring a module, it needs to be installed&lt;br /&gt;
$ terraform plan&lt;br /&gt;
$ terraform apply&lt;br /&gt;
&lt;br /&gt;
$ cd /opt/salt/nasqueron-operations&lt;br /&gt;
$ salt windriver state.sls_id /usr/local/etc/secrets/rhyne-wyse.yaml roles/reports/rhyne-wyse/config&lt;br /&gt;
$ salt windriver state.sls_id /srv/viperserv/.credentials roles/viperserv/eggdrop/config&lt;br /&gt;
# Missing for router&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Table of Terraform states ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Terraform and OpenBao states&lt;br /&gt;
|-&lt;br /&gt;
! Configuration !! State back-end !! Path !! Software to use&lt;br /&gt;
|-&lt;br /&gt;
| openbao || On disk || /opt/salt/nasqueron-operations/terraform/openbao/terraform.tfstate || Terraform&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
On disk paths are stored in Complector.&lt;br /&gt;
&lt;br /&gt;
== Troubleshoot ==&lt;br /&gt;
=== Error: Module not installed ===&lt;br /&gt;
&lt;br /&gt;
You need to run &amp;lt;code&amp;gt;tofu init&amp;lt;/code&amp;gt; to prepare for any new provider.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;shell&amp;quot;&amp;gt;&lt;br /&gt;
$ tofu plan&lt;br /&gt;
&lt;br /&gt;
│ Error: Module not installed&lt;br /&gt;
│ &lt;br /&gt;
│   on rhyne_wyse.tf line 23:&lt;br /&gt;
│   23: module &amp;quot;rhyne_wyse_approle&amp;quot; {&lt;br /&gt;
│ &lt;br /&gt;
│ This module is not yet installed. Run &amp;quot;tofu init&amp;quot; to install all modules required by this configuration.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Error: Incompatible provider version ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;shell&amp;quot;&amp;gt;&lt;br /&gt;
$ tofu init&lt;br /&gt;
&lt;br /&gt;
Initializing the backend...&lt;br /&gt;
Initializing modules...&lt;br /&gt;
- rhyne_wyse_approle in modules/app_credentials&lt;br /&gt;
&lt;br /&gt;
Initializing provider plugins...&lt;br /&gt;
- Finding hashicorp/vault versions matching &amp;quot;5.3.0&amp;quot;...&lt;br /&gt;
╷&lt;br /&gt;
│ Error: Incompatible provider version&lt;br /&gt;
│ &lt;br /&gt;
│ Provider registry.opentofu.org/hashicorp/vault v5.3.0 does not have a package available for your current platform, freebsd_amd64.&lt;br /&gt;
│ &lt;br /&gt;
│ Provider releases are separate from OpenTofu CLI releases, so not all providers are available for all platforms. Other versions of this provider may have different platforms supported.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On OpenTofu, some modules are only compiled for Linux, not for FreeBSD.&lt;br /&gt;
Switch to Terraform pending a solution to help the OpenTofu builds.&lt;br /&gt;
&lt;br /&gt;
[[Category:Operations grimoire]]&lt;br /&gt;
[[Category:Terraform]]&lt;/div&gt;</summary>
		<author><name>Dereckson</name></author>
	</entry>
	<entry>
		<id>https://agora.nasqueron.org/index.php?title=Operations_grimoire/Vault&amp;diff=2490</id>
		<title>Operations grimoire/Vault</title>
		<link rel="alternate" type="text/html" href="https://agora.nasqueron.org/index.php?title=Operations_grimoire/Vault&amp;diff=2490"/>
		<updated>2026-03-22T18:59:45Z</updated>

		<summary type="html">&lt;p&gt;Dereckson: /* Get an admin-level token */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;This page currently documents Vault installed on complector as part of {{Ops file|roles/vault/}}. It doesn&#039;t document Docker or shellserver installation. See [[Operations grimoire/Eglide/Vault]] and [[Dev zone/Vault]].&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Hashicorp Vault allows to manage credentials and is currently used:&lt;br /&gt;
&lt;br /&gt;
* to provision credentials through Salt &lt;br /&gt;
* to allow applications to fetch credentials&lt;br /&gt;
* to emit certificates for the private network applications&lt;br /&gt;
* to store credentials used by the Nasqueron Operations SIG beings&lt;br /&gt;
&lt;br /&gt;
Vault policies are fully managed through Salt in the operations repository.&lt;br /&gt;
&lt;br /&gt;
Vault has been selected in 2016 for secrets management.&lt;br /&gt;
&lt;br /&gt;
== Vault reference ==&lt;br /&gt;
=== kv engine ===&lt;br /&gt;
The kv engine contains the following paths:&lt;br /&gt;
&lt;br /&gt;
  * ops/secrets: credentials like passwords, API tokens, private keys deployed to servers - a reference for machines&lt;br /&gt;
  * ops/internal: credentials to third-party services internally shared amongst ops - a reference for humans&lt;br /&gt;
  * ops/privacy: privacy information&lt;br /&gt;
&lt;br /&gt;
==== Secrets ====&lt;br /&gt;
Secrets are directly and manually managed in Vault. If we need to run a disaster recovery procedure, we&#039;ll roll any secret by defining them again and deploy from rOPS those new secrets.&lt;br /&gt;
&lt;br /&gt;
==== Privacy data ====&lt;br /&gt;
Personal identity information (PII) shared inside the Nasqueron Operations squad are more convenient to manage as a repository.&lt;br /&gt;
&lt;br /&gt;
Such access to the repository is restricted to commit data, and ensure this data is deployed to the servers needing it. Any other use isn&#039;t allowed.&lt;br /&gt;
&lt;br /&gt;
Information to the repository is then published in Vault, and referred in rOPS as Vault credentials.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The ops/privacy path is only intended for PII of current or previous members of the Ops SIG, like IP addresses allowed to connect to restricted resources like the ops VPN. This is not acceptable to put 3rd party information in this repository.&lt;br /&gt;
&lt;br /&gt;
=== pki engine ===&lt;br /&gt;
Services listening to private IPs use the Vault PKI to generate certificates: &lt;br /&gt;
&lt;br /&gt;
* pki_root: root CA, certificate available at https://api.nasqueron.org/infra/security/pki/root/ca&lt;br /&gt;
* pki_vault: intermediate CA used for Vault itself&lt;br /&gt;
&lt;br /&gt;
Certificates should be issued short-term and frequently renewed by automated services.&lt;br /&gt;
&lt;br /&gt;
=== transit engine ===&lt;br /&gt;
Encryption as a service is available for applications under /transit path.&lt;br /&gt;
&lt;br /&gt;
See https://learn.hashicorp.com/tutorials/vault/eaas-transit.&lt;br /&gt;
&lt;br /&gt;
Applications should use a policy restricting to a subpath for that app, not to the whole engine.&lt;br /&gt;
&lt;br /&gt;
=== Users accounts ===&lt;br /&gt;
&lt;br /&gt;
Members of the Operations SIG need an access to Vault to create and maintain credentials.&lt;br /&gt;
&lt;br /&gt;
Currently, we use tokens. To generate a token:&lt;br /&gt;
&lt;br /&gt;
     vault token create -policy=admin&lt;br /&gt;
&lt;br /&gt;
To connect to Vault with a token from a devserver (e.g. WindRiver), you need:&lt;br /&gt;
&lt;br /&gt;
# Store the token in &amp;lt;code&amp;gt;$HOME/.vault-token&amp;lt;/code&amp;gt;&lt;br /&gt;
# Define environment variable VAULT_ADDR: &amp;lt;code&amp;gt;export VAULT_ADDR=https://172.27.27.7:8200&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Tokens need to be frequently renew (before expiration) with &amp;lt;code&amp;gt;vault renew&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Salt configuration ==&lt;br /&gt;
=== Get a secret through Salt ===&lt;br /&gt;
The information in the ops/secrets and ops/privacy kv engines are integrated in the Salt pillar:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;yaml&amp;quot;&amp;gt;&lt;br /&gt;
ext_pillar:&lt;br /&gt;
  # Credentials to deploy to servers&lt;br /&gt;
  - vault:&lt;br /&gt;
       conf: path=ops/secrets&lt;br /&gt;
       nesting_key: credentials&lt;br /&gt;
&lt;br /&gt;
  # Personal identity information from Nasqueron Operations SIG members&lt;br /&gt;
  - vault:&lt;br /&gt;
       conf: path=ops/privacy&lt;br /&gt;
       nesting_key: privacy&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can then access to this information in Salt states using the following references:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Access to Salt data&lt;br /&gt;
|-&lt;br /&gt;
! Category !! Example of path in Vault !! Example of pillar key in Salt&lt;br /&gt;
|-&lt;br /&gt;
| Secrets || ops/secrets/foo || pillar[&#039;credentials&#039;][&#039;foo&#039;]&lt;br /&gt;
|-&lt;br /&gt;
| Privacy data || ops/privacy/ops-cidr || pillar[&#039;privacy&#039;][&#039;ops-cidr&#039;]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The ops/internal paths aren&#039;t accessible through Vault.&lt;br /&gt;
&lt;br /&gt;
=== Policies ===&lt;br /&gt;
&lt;br /&gt;
Policies are managed in {{Ops file|pillar/credentials/vault.sls}}.&lt;br /&gt;
&lt;br /&gt;
For Salt, we deploy secrets to servers, policy management for a node consist to provide the list of secrets a role should have access to, generally in &#039;&#039;&#039;vault_secrets_by_role&#039;&#039;&#039; dictionary.&lt;br /&gt;
&lt;br /&gt;
For other applications:&lt;br /&gt;
* create a policy .hcl in &amp;lt;code&amp;gt;roles/vault/policies/files/&amp;lt;/code&amp;gt;&lt;br /&gt;
* declare the policy in the pillar under &amp;lt;code&amp;gt;vault_policies&amp;lt;/code&amp;gt; list, it should match the .hcl file (without the extension or the path)&lt;br /&gt;
* run the repository tests to check if both information matches ; to only run that part, use &amp;lt;code&amp;gt;cd _tests &amp;amp;&amp;amp; python3 -m unittest discover pillar/credentials/&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To add only an application policy, Salt can be deployed like this:&lt;br /&gt;
&lt;br /&gt;
    salt complector state.sls_id vault_policy_airflow roles/vault/policies&lt;br /&gt;
&lt;br /&gt;
Salt policies can be tested by specifying the node name:&lt;br /&gt;
&lt;br /&gt;
    salt complector state.sls_id salt-node-windriver roles/vault/policies test=True&lt;br /&gt;
&lt;br /&gt;
=== DRP ===&lt;br /&gt;
Any step we need to do to configure the engines should be added to the {{ops file|roles/vault/bootstrap}} unit.&lt;br /&gt;
&lt;br /&gt;
If we need to recover Vault, two solutions are available:&lt;br /&gt;
* restore the storage, to keep data (credentials, certificates including the root CA one)&lt;br /&gt;
* recreate it from scratch through the roles/vault/bootstrap unit&lt;br /&gt;
&lt;br /&gt;
== Howto ==&lt;br /&gt;
=== Allow a new application to authenticate to Vault ===&lt;br /&gt;
Applications need a policy and an authentication method, for example here for an application called yourservice with AppRole with secret_id and role_id:&lt;br /&gt;
# Create a new policy in operations repository: {{D|3270}}&lt;br /&gt;
# Deploy it from Complector with &amp;lt;code&amp;gt;salt complector state.sls_id vault_policy_yourservice roles/vault/policies&amp;lt;/code&amp;gt;&lt;br /&gt;
# Create an approle matching that policy: &amp;lt;code&amp;gt;vault write auth/approle/role/yourservice token_policies=&amp;quot;yourservice&amp;quot; token_ttl=1h token_max_ttl=4h&amp;lt;/code&amp;gt;&lt;br /&gt;
# Get role_id with &amp;lt;code&amp;gt;vault read auth/approle/role/yourservice/role-id&amp;lt;/code&amp;gt;&lt;br /&gt;
# Get secret_id with &amp;lt;code&amp;gt;vault write -force auth/approle/role/yourservice/secret-id&amp;lt;/code&amp;gt;&lt;br /&gt;
# If you wish Salt to provision those credentials during your service deployment, probably a good idea to write them too: &amp;lt;code&amp;gt;vault kv put secrets/nasqueron/yourservice/vault username=role-id password=secret-id&amp;lt;/code&amp;gt; [to skip if you don&#039;t use Salt to provision role-id and secret-id]&lt;br /&gt;
&lt;br /&gt;
=== Get an admin-level token ===&lt;br /&gt;
Ops can use the self-service hvac script to get a token valid for 30 days:&lt;br /&gt;
&lt;br /&gt;
    ssh complector&lt;br /&gt;
    cd /opt/salt/nasqueron-operations&lt;br /&gt;
    sudo ./utils/vault/issue-admin-token.py&lt;br /&gt;
&lt;br /&gt;
If Vault certificate has expired, add the `--insecure` argument.&lt;br /&gt;
&lt;br /&gt;
You can also create a $HOME/bin/vault-login helper script:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight language=&amp;quot;sh&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
&lt;br /&gt;
touch $HOME/.vault-token&lt;br /&gt;
chmod 600 $HOME/.vault-token&lt;br /&gt;
ssh complector sudo /opt/salt/nasqueron-operations/utils/vault/issue-admin-token.py | tr -d &#039;\n&#039; &amp;gt; $HOME/.vault-token&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Troubleshoot ==&lt;br /&gt;
=== Connecting to Vault ===&lt;br /&gt;
==== Access to web UI ====&lt;br /&gt;
Vault isn&#039;t listening any public IP, but accept connections from internal network, so you can open a SSH tunnel against &amp;lt;code&amp;gt;complector:8200&amp;lt;/code&amp;gt; and then browse https://localhost:8200:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;ssh -L 8200:complector:8200 router-001.nasqueron.org&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== curl: (60) SSL certificate problem ====&lt;br /&gt;
Curl is compiled against a certificate bundle (&amp;lt;code&amp;gt;curl-config --ca&amp;lt;/code&amp;gt; for the path). That bundle doesn&#039;t contain the pki_root certificate. We deploy this certificate in /etc/ssl/certs, but curl won&#039;t check there if not instructed to. &lt;br /&gt;
&lt;br /&gt;
If you build an immutable environment like a container, add the certificate to the bundle.&lt;br /&gt;
&lt;br /&gt;
On other machines, create a curl configuration file in ~/.curlrc (it doesn&#039;t seem currently possible to create a system one) with &amp;lt;code&amp;gt;capath=/etc/ssl/certs&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
If you&#039;ve still the issue after that, check two things:&lt;br /&gt;
* with &amp;lt;code&amp;gt;curl -v&amp;lt;/code&amp;gt;, the path should correctly there: &amp;lt;code&amp;gt;*  CApath: /etc/ssl/certs&amp;lt;/code&amp;gt; in addition to a CAfile.&lt;br /&gt;
* with &amp;lt;code&amp;gt;file /etc/ssl/certs/* | grep -i nasqueron&amp;lt;/code&amp;gt; you should have a result ; if not, put the certificate in /usr/local/share/certs and relaunch the tool to link it in /etc/ssl/certs, for example &amp;lt;code&amp;gt;certctl rehash&amp;lt;/code&amp;gt; on FreeBSD (needs root access).&lt;br /&gt;
&lt;br /&gt;
=== Certificates ===&lt;br /&gt;
==== How to unseal when certificate have expired? ====&lt;br /&gt;
Use the web UI through SSH tunnel.&lt;br /&gt;
&lt;br /&gt;
==== Renew Vault HTTP certificates ====&lt;br /&gt;
&lt;br /&gt;
Vault uses TLS certificates managed by its own CA. That can create a chicken/egg issue if certificates have expired to connect to it, as the Vault client strictly requires valid TLS certificated to issue commands to renew certificates.&lt;br /&gt;
&lt;br /&gt;
Connect to the web UI works as your browser is able to bypass certificate requirement. Opening a SSH tunnel with &amp;lt;code&amp;gt;-L 8200:complector:8200&amp;lt;/code&amp;gt; should work for that.&lt;br /&gt;
&lt;br /&gt;
Certificates configuration is available at [https://devcentral.nasqueron.org/D2639 D2639].&lt;br /&gt;
&lt;br /&gt;
The web UI doesn&#039;t offer a comprehensive sets of widgets to generate certificates. You can instead use the &#039;&#039;Vault Browser CLI&#039;&#039; to run Vault CLI commands from the web UI. The signing operation can be done through endpoint configuration UI.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;background-color: indianred; border: solid 3px black; color:white; font-size: large; padding: 2em;&amp;quot;&amp;gt;Automation for this part is being tested.&lt;br /&gt;
&lt;br /&gt;
You can preview automation proposal in /home/dereckson/sandbox/vault/renew-certificates on Complector.&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Based on current D2639 state (2023-01), you can do the following:&lt;br /&gt;
* Has intermediate authority certificate expired? [old instructions, currently not valid anymore]&lt;br /&gt;
** Web console: &amp;lt;code&amp;gt;write -format=json pki_vault/intermediate/generate/internal common_name=&amp;quot;nasqueron.drake Intermediate Authority&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
** At https://localhost:8200/ui/vault/secrets/pki_vault/pki/roles/nasqueron-drake you can use the sign intermediate button to sign it, don&#039;t forget to fill the following information:&lt;br /&gt;
*** CSR, pick from console the .data.csr output from JSON response&lt;br /&gt;
*** Format: pem_bundle&lt;br /&gt;
*** TTL: 100 days&lt;br /&gt;
*** Common name: &amp;quot;nasqueron.drake Intermediate Authority&amp;quot;&lt;br /&gt;
*** Organization: Nasqueron&lt;br /&gt;
*** Organization unit: Nasqueron Operations SIG&lt;br /&gt;
*** Country: BE&lt;br /&gt;
** Follow the warning instruction: copy the certificate bundle, and in pki_vault, use Set signed intermediate to set the certificate as intermediate one. That will create a new issuer, fetch the name in &amp;quot;issuers&amp;quot;.&lt;br /&gt;
** Save also the certificate bundle to /usr/local/share/certs/nasqueron-vault-intermediate.crt&lt;br /&gt;
** Edit the nasqueron-drake role to use your new issuer name&lt;br /&gt;
* Has complector.nasqueron.drake certificate has expired?&lt;br /&gt;
** Web console: &amp;lt;code&amp;gt;write -format=json pki_vault/issue/nasqueron-drake common_name=complector.nasqueron.drake ttl=2160h ip_sans=127.0.0.1,172.27.27.7&amp;lt;/code&amp;gt;, save the output in /usr/local/etc/certificates/vault files:&lt;br /&gt;
*** .data.certificate to certificate.pem&lt;br /&gt;
*** .data.issuing_ca to ca.pem&lt;br /&gt;
*** .data.private_key to private.key (careful how you replace the \n, if you use Python REPL, do it on Complector itself and get rid of the history with &amp;lt;code&amp;gt;import readline ; readline.clear_history()&amp;lt;/code&amp;gt;)&lt;br /&gt;
** Prepare the fullchain bundle with &amp;lt;code&amp;gt;cat certificate.pem ca.pem &amp;gt; fullchain.pem&amp;lt;/code&amp;gt;&lt;br /&gt;
** Send a SIGHUP signal to Vault to reload configuration with &amp;lt;code&amp;gt;kill -1 &amp;lt;Vault PID&amp;gt;&amp;lt;/code&amp;gt;, HTTP server should pick new certificate and you can know directly use the vault command. Vault configuration currently uses fullchain.pem and private.key.&lt;br /&gt;
&lt;br /&gt;
CSR uses &amp;lt;code&amp;gt;line1\nline2\nline3&amp;lt;/code&amp;gt; format in JSON. You can use a Python REPL with print(&amp;quot;...&amp;quot;) to print the CSR in several lines. CSR isn&#039;t confidential information, key is protected in Vault and never exposed.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;jq.&#039;&#039;&#039; Another tool that can help is &amp;lt;code&amp;gt;jq&amp;lt;/code&amp;gt;. For example, &amp;lt;code&amp;gt;cat certificate.json | jq -r .data.certificate &amp;gt; /usr/local/etc/certificates/vault/certificate.pem&amp;lt;/code&amp;gt; will save it in multiline format.&lt;br /&gt;
&lt;br /&gt;
If you get an issue about private key missing at Set signed intermediate step, don&#039;t forget you&#039;re setting an intermediate certificate for pki_vault, and not for pki_root, set that here: https://localhost:8200/ui/vault/settings/secrets/configure/pki_vault/cert&lt;br /&gt;
&lt;br /&gt;
Paths where to store certificates matter:&lt;br /&gt;
* pki_root certificates are stored in /usr/local/share/certs&lt;br /&gt;
* pki_vault certificates are stored in /usr/local/etc/certificates/vault&lt;br /&gt;
&lt;br /&gt;
Ensure `private.key` belongs to user `vault` and receives a correct chmod like 400.&lt;br /&gt;
&lt;br /&gt;
==== Services known to break when a certificate is expired ====&lt;br /&gt;
&lt;br /&gt;
* Salt, but that&#039;s ad-hoc and explicit&lt;br /&gt;
* Sentry containers: &amp;lt;code&amp;gt;sudo docker ps -a | grep sentry | grep -v &amp;quot;Up &amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Salt ===&lt;br /&gt;
==== Policy for a node doesn&#039;t contain new secret entry ====&lt;br /&gt;
If the policies are attached to a new role:&lt;br /&gt;
&lt;br /&gt;
# Ensure new secret have been added for the right role in {{Ops file|pillar/credentials/vault.sls}}&lt;br /&gt;
#* If missing, validate afterwards with &amp;lt;code&amp;gt;salt complector pillar.get vault_secrets_by_role:yourrole&amp;lt;/code&amp;gt;&lt;br /&gt;
#* You need to refresh the pillar if still missing: &amp;lt;code&amp;gt;salt complector saltutil.refresh_pillar&amp;lt;/code&amp;gt;&lt;br /&gt;
# Ensure role has been added to {{Ops file|pillar/nodes/nodes.sls}} and NetBox&lt;br /&gt;
#* If missing, refresh pillar afterwards&lt;br /&gt;
#* Validate with &amp;lt;code&amp;gt;salt complector node.get roles &amp;lt;server name&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
# Final check: &amp;lt;code&amp;gt;salt complector state.sls_id salt-node-&amp;lt;server name&amp;gt; roles/vault/policies test=True&amp;lt;/code&amp;gt;&lt;br /&gt;
# If diff is complicated to read, check the full policies document by role: &amp;lt;code&amp;gt;salt complector credentials.build_policies_by_node&amp;lt;/code&amp;gt;&lt;br /&gt;
#* Secret path present? Check the policy isn&#039;t already up-to-date: &amp;lt;code&amp;gt;vault policy read salt-node-&amp;lt;server name&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== credentials.vault_policy_present returns Bad Request ====&lt;br /&gt;
&lt;br /&gt;
Vault returns a 400 error if the policy format is incorrect.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Case 1.&#039;&#039;&#039; The state ID starts by &amp;lt;code&amp;gt;vault_policy_&amp;lt;/code&amp;gt;. You manually added a file to roles/vault/policies/file: this error means Vault API founds a syntax error in it. You can use https://github.com/mschuchard/linter-vault-policy if you use Pulsar (ex Atom) to lint those files.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Case 2.&#039;&#039;&#039; The state ID starts by anything else. The policy has been generated through _modules/credentials.py.&lt;br /&gt;
&lt;br /&gt;
Check if the pillar values added are correct:&lt;br /&gt;
* if not, add a test in &amp;lt;code&amp;gt;_tests/pillar/credentials/test_vault.py&amp;lt;/code&amp;gt; to detect the case&lt;br /&gt;
* if yes, there is an issue with the Python module code to fix&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example of Salt output.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
----------&lt;br /&gt;
          ID: vault_policy_admin&lt;br /&gt;
    Function: credentials.vault_policy_present&lt;br /&gt;
        Name: admin&lt;br /&gt;
      Result: False&lt;br /&gt;
     Comment: Failed to change policy: Bad Request&lt;br /&gt;
     Started: 13:45:14.162421&lt;br /&gt;
    Duration: 76.168 ms&lt;br /&gt;
     Changes:&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Operations grimoire]]&lt;br /&gt;
[[Category:Vault]]&lt;/div&gt;</summary>
		<author><name>Dereckson</name></author>
	</entry>
	<entry>
		<id>https://agora.nasqueron.org/index.php?title=Operations_grimoire/Vault&amp;diff=2489</id>
		<title>Operations grimoire/Vault</title>
		<link rel="alternate" type="text/html" href="https://agora.nasqueron.org/index.php?title=Operations_grimoire/Vault&amp;diff=2489"/>
		<updated>2026-03-22T18:57:55Z</updated>

		<summary type="html">&lt;p&gt;Dereckson: /* Get an admin-level token */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;This page currently documents Vault installed on complector as part of {{Ops file|roles/vault/}}. It doesn&#039;t document Docker or shellserver installation. See [[Operations grimoire/Eglide/Vault]] and [[Dev zone/Vault]].&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Hashicorp Vault allows to manage credentials and is currently used:&lt;br /&gt;
&lt;br /&gt;
* to provision credentials through Salt &lt;br /&gt;
* to allow applications to fetch credentials&lt;br /&gt;
* to emit certificates for the private network applications&lt;br /&gt;
* to store credentials used by the Nasqueron Operations SIG beings&lt;br /&gt;
&lt;br /&gt;
Vault policies are fully managed through Salt in the operations repository.&lt;br /&gt;
&lt;br /&gt;
Vault has been selected in 2016 for secrets management.&lt;br /&gt;
&lt;br /&gt;
== Vault reference ==&lt;br /&gt;
=== kv engine ===&lt;br /&gt;
The kv engine contains the following paths:&lt;br /&gt;
&lt;br /&gt;
  * ops/secrets: credentials like passwords, API tokens, private keys deployed to servers - a reference for machines&lt;br /&gt;
  * ops/internal: credentials to third-party services internally shared amongst ops - a reference for humans&lt;br /&gt;
  * ops/privacy: privacy information&lt;br /&gt;
&lt;br /&gt;
==== Secrets ====&lt;br /&gt;
Secrets are directly and manually managed in Vault. If we need to run a disaster recovery procedure, we&#039;ll roll any secret by defining them again and deploy from rOPS those new secrets.&lt;br /&gt;
&lt;br /&gt;
==== Privacy data ====&lt;br /&gt;
Personal identity information (PII) shared inside the Nasqueron Operations squad are more convenient to manage as a repository.&lt;br /&gt;
&lt;br /&gt;
Such access to the repository is restricted to commit data, and ensure this data is deployed to the servers needing it. Any other use isn&#039;t allowed.&lt;br /&gt;
&lt;br /&gt;
Information to the repository is then published in Vault, and referred in rOPS as Vault credentials.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The ops/privacy path is only intended for PII of current or previous members of the Ops SIG, like IP addresses allowed to connect to restricted resources like the ops VPN. This is not acceptable to put 3rd party information in this repository.&lt;br /&gt;
&lt;br /&gt;
=== pki engine ===&lt;br /&gt;
Services listening to private IPs use the Vault PKI to generate certificates: &lt;br /&gt;
&lt;br /&gt;
* pki_root: root CA, certificate available at https://api.nasqueron.org/infra/security/pki/root/ca&lt;br /&gt;
* pki_vault: intermediate CA used for Vault itself&lt;br /&gt;
&lt;br /&gt;
Certificates should be issued short-term and frequently renewed by automated services.&lt;br /&gt;
&lt;br /&gt;
=== transit engine ===&lt;br /&gt;
Encryption as a service is available for applications under /transit path.&lt;br /&gt;
&lt;br /&gt;
See https://learn.hashicorp.com/tutorials/vault/eaas-transit.&lt;br /&gt;
&lt;br /&gt;
Applications should use a policy restricting to a subpath for that app, not to the whole engine.&lt;br /&gt;
&lt;br /&gt;
=== Users accounts ===&lt;br /&gt;
&lt;br /&gt;
Members of the Operations SIG need an access to Vault to create and maintain credentials.&lt;br /&gt;
&lt;br /&gt;
Currently, we use tokens. To generate a token:&lt;br /&gt;
&lt;br /&gt;
     vault token create -policy=admin&lt;br /&gt;
&lt;br /&gt;
To connect to Vault with a token from a devserver (e.g. WindRiver), you need:&lt;br /&gt;
&lt;br /&gt;
# Store the token in &amp;lt;code&amp;gt;$HOME/.vault-token&amp;lt;/code&amp;gt;&lt;br /&gt;
# Define environment variable VAULT_ADDR: &amp;lt;code&amp;gt;export VAULT_ADDR=https://172.27.27.7:8200&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Tokens need to be frequently renew (before expiration) with &amp;lt;code&amp;gt;vault renew&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Salt configuration ==&lt;br /&gt;
=== Get a secret through Salt ===&lt;br /&gt;
The information in the ops/secrets and ops/privacy kv engines are integrated in the Salt pillar:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;yaml&amp;quot;&amp;gt;&lt;br /&gt;
ext_pillar:&lt;br /&gt;
  # Credentials to deploy to servers&lt;br /&gt;
  - vault:&lt;br /&gt;
       conf: path=ops/secrets&lt;br /&gt;
       nesting_key: credentials&lt;br /&gt;
&lt;br /&gt;
  # Personal identity information from Nasqueron Operations SIG members&lt;br /&gt;
  - vault:&lt;br /&gt;
       conf: path=ops/privacy&lt;br /&gt;
       nesting_key: privacy&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can then access to this information in Salt states using the following references:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Access to Salt data&lt;br /&gt;
|-&lt;br /&gt;
! Category !! Example of path in Vault !! Example of pillar key in Salt&lt;br /&gt;
|-&lt;br /&gt;
| Secrets || ops/secrets/foo || pillar[&#039;credentials&#039;][&#039;foo&#039;]&lt;br /&gt;
|-&lt;br /&gt;
| Privacy data || ops/privacy/ops-cidr || pillar[&#039;privacy&#039;][&#039;ops-cidr&#039;]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The ops/internal paths aren&#039;t accessible through Vault.&lt;br /&gt;
&lt;br /&gt;
=== Policies ===&lt;br /&gt;
&lt;br /&gt;
Policies are managed in {{Ops file|pillar/credentials/vault.sls}}.&lt;br /&gt;
&lt;br /&gt;
For Salt, we deploy secrets to servers, policy management for a node consist to provide the list of secrets a role should have access to, generally in &#039;&#039;&#039;vault_secrets_by_role&#039;&#039;&#039; dictionary.&lt;br /&gt;
&lt;br /&gt;
For other applications:&lt;br /&gt;
* create a policy .hcl in &amp;lt;code&amp;gt;roles/vault/policies/files/&amp;lt;/code&amp;gt;&lt;br /&gt;
* declare the policy in the pillar under &amp;lt;code&amp;gt;vault_policies&amp;lt;/code&amp;gt; list, it should match the .hcl file (without the extension or the path)&lt;br /&gt;
* run the repository tests to check if both information matches ; to only run that part, use &amp;lt;code&amp;gt;cd _tests &amp;amp;&amp;amp; python3 -m unittest discover pillar/credentials/&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To add only an application policy, Salt can be deployed like this:&lt;br /&gt;
&lt;br /&gt;
    salt complector state.sls_id vault_policy_airflow roles/vault/policies&lt;br /&gt;
&lt;br /&gt;
Salt policies can be tested by specifying the node name:&lt;br /&gt;
&lt;br /&gt;
    salt complector state.sls_id salt-node-windriver roles/vault/policies test=True&lt;br /&gt;
&lt;br /&gt;
=== DRP ===&lt;br /&gt;
Any step we need to do to configure the engines should be added to the {{ops file|roles/vault/bootstrap}} unit.&lt;br /&gt;
&lt;br /&gt;
If we need to recover Vault, two solutions are available:&lt;br /&gt;
* restore the storage, to keep data (credentials, certificates including the root CA one)&lt;br /&gt;
* recreate it from scratch through the roles/vault/bootstrap unit&lt;br /&gt;
&lt;br /&gt;
== Howto ==&lt;br /&gt;
=== Allow a new application to authenticate to Vault ===&lt;br /&gt;
Applications need a policy and an authentication method, for example here for an application called yourservice with AppRole with secret_id and role_id:&lt;br /&gt;
# Create a new policy in operations repository: {{D|3270}}&lt;br /&gt;
# Deploy it from Complector with &amp;lt;code&amp;gt;salt complector state.sls_id vault_policy_yourservice roles/vault/policies&amp;lt;/code&amp;gt;&lt;br /&gt;
# Create an approle matching that policy: &amp;lt;code&amp;gt;vault write auth/approle/role/yourservice token_policies=&amp;quot;yourservice&amp;quot; token_ttl=1h token_max_ttl=4h&amp;lt;/code&amp;gt;&lt;br /&gt;
# Get role_id with &amp;lt;code&amp;gt;vault read auth/approle/role/yourservice/role-id&amp;lt;/code&amp;gt;&lt;br /&gt;
# Get secret_id with &amp;lt;code&amp;gt;vault write -force auth/approle/role/yourservice/secret-id&amp;lt;/code&amp;gt;&lt;br /&gt;
# If you wish Salt to provision those credentials during your service deployment, probably a good idea to write them too: &amp;lt;code&amp;gt;vault kv put secrets/nasqueron/yourservice/vault username=role-id password=secret-id&amp;lt;/code&amp;gt; [to skip if you don&#039;t use Salt to provision role-id and secret-id]&lt;br /&gt;
&lt;br /&gt;
=== Get an admin-level token ===&lt;br /&gt;
Ops can use the self-service hvac script to get a token valid for 30 days:&lt;br /&gt;
&lt;br /&gt;
    ssh complector&lt;br /&gt;
    cd /opt/salt/nasqueron-operations&lt;br /&gt;
    sudo ./utils/vault/issue-admin-token.py&lt;br /&gt;
&lt;br /&gt;
If Vault certificate has expired, add the `--insecure` argument.&lt;br /&gt;
&lt;br /&gt;
You can also automate this as a oneliner to store the token in the default token file:&lt;br /&gt;
&lt;br /&gt;
    ssh complector sudo /opt/salt/nasqueron-operations/utils/vault/issue-admin-token.py &amp;gt; ~/.vault-token ; chmod 600 ~/.vault-token&lt;br /&gt;
&lt;br /&gt;
== Troubleshoot ==&lt;br /&gt;
=== Connecting to Vault ===&lt;br /&gt;
==== Access to web UI ====&lt;br /&gt;
Vault isn&#039;t listening any public IP, but accept connections from internal network, so you can open a SSH tunnel against &amp;lt;code&amp;gt;complector:8200&amp;lt;/code&amp;gt; and then browse https://localhost:8200:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;ssh -L 8200:complector:8200 router-001.nasqueron.org&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== curl: (60) SSL certificate problem ====&lt;br /&gt;
Curl is compiled against a certificate bundle (&amp;lt;code&amp;gt;curl-config --ca&amp;lt;/code&amp;gt; for the path). That bundle doesn&#039;t contain the pki_root certificate. We deploy this certificate in /etc/ssl/certs, but curl won&#039;t check there if not instructed to. &lt;br /&gt;
&lt;br /&gt;
If you build an immutable environment like a container, add the certificate to the bundle.&lt;br /&gt;
&lt;br /&gt;
On other machines, create a curl configuration file in ~/.curlrc (it doesn&#039;t seem currently possible to create a system one) with &amp;lt;code&amp;gt;capath=/etc/ssl/certs&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
If you&#039;ve still the issue after that, check two things:&lt;br /&gt;
* with &amp;lt;code&amp;gt;curl -v&amp;lt;/code&amp;gt;, the path should correctly there: &amp;lt;code&amp;gt;*  CApath: /etc/ssl/certs&amp;lt;/code&amp;gt; in addition to a CAfile.&lt;br /&gt;
* with &amp;lt;code&amp;gt;file /etc/ssl/certs/* | grep -i nasqueron&amp;lt;/code&amp;gt; you should have a result ; if not, put the certificate in /usr/local/share/certs and relaunch the tool to link it in /etc/ssl/certs, for example &amp;lt;code&amp;gt;certctl rehash&amp;lt;/code&amp;gt; on FreeBSD (needs root access).&lt;br /&gt;
&lt;br /&gt;
=== Certificates ===&lt;br /&gt;
==== How to unseal when certificate have expired? ====&lt;br /&gt;
Use the web UI through SSH tunnel.&lt;br /&gt;
&lt;br /&gt;
==== Renew Vault HTTP certificates ====&lt;br /&gt;
&lt;br /&gt;
Vault uses TLS certificates managed by its own CA. That can create a chicken/egg issue if certificates have expired to connect to it, as the Vault client strictly requires valid TLS certificated to issue commands to renew certificates.&lt;br /&gt;
&lt;br /&gt;
Connect to the web UI works as your browser is able to bypass certificate requirement. Opening a SSH tunnel with &amp;lt;code&amp;gt;-L 8200:complector:8200&amp;lt;/code&amp;gt; should work for that.&lt;br /&gt;
&lt;br /&gt;
Certificates configuration is available at [https://devcentral.nasqueron.org/D2639 D2639].&lt;br /&gt;
&lt;br /&gt;
The web UI doesn&#039;t offer a comprehensive sets of widgets to generate certificates. You can instead use the &#039;&#039;Vault Browser CLI&#039;&#039; to run Vault CLI commands from the web UI. The signing operation can be done through endpoint configuration UI.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;background-color: indianred; border: solid 3px black; color:white; font-size: large; padding: 2em;&amp;quot;&amp;gt;Automation for this part is being tested.&lt;br /&gt;
&lt;br /&gt;
You can preview automation proposal in /home/dereckson/sandbox/vault/renew-certificates on Complector.&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Based on current D2639 state (2023-01), you can do the following:&lt;br /&gt;
* Has intermediate authority certificate expired? [old instructions, currently not valid anymore]&lt;br /&gt;
** Web console: &amp;lt;code&amp;gt;write -format=json pki_vault/intermediate/generate/internal common_name=&amp;quot;nasqueron.drake Intermediate Authority&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
** At https://localhost:8200/ui/vault/secrets/pki_vault/pki/roles/nasqueron-drake you can use the sign intermediate button to sign it, don&#039;t forget to fill the following information:&lt;br /&gt;
*** CSR, pick from console the .data.csr output from JSON response&lt;br /&gt;
*** Format: pem_bundle&lt;br /&gt;
*** TTL: 100 days&lt;br /&gt;
*** Common name: &amp;quot;nasqueron.drake Intermediate Authority&amp;quot;&lt;br /&gt;
*** Organization: Nasqueron&lt;br /&gt;
*** Organization unit: Nasqueron Operations SIG&lt;br /&gt;
*** Country: BE&lt;br /&gt;
** Follow the warning instruction: copy the certificate bundle, and in pki_vault, use Set signed intermediate to set the certificate as intermediate one. That will create a new issuer, fetch the name in &amp;quot;issuers&amp;quot;.&lt;br /&gt;
** Save also the certificate bundle to /usr/local/share/certs/nasqueron-vault-intermediate.crt&lt;br /&gt;
** Edit the nasqueron-drake role to use your new issuer name&lt;br /&gt;
* Has complector.nasqueron.drake certificate has expired?&lt;br /&gt;
** Web console: &amp;lt;code&amp;gt;write -format=json pki_vault/issue/nasqueron-drake common_name=complector.nasqueron.drake ttl=2160h ip_sans=127.0.0.1,172.27.27.7&amp;lt;/code&amp;gt;, save the output in /usr/local/etc/certificates/vault files:&lt;br /&gt;
*** .data.certificate to certificate.pem&lt;br /&gt;
*** .data.issuing_ca to ca.pem&lt;br /&gt;
*** .data.private_key to private.key (careful how you replace the \n, if you use Python REPL, do it on Complector itself and get rid of the history with &amp;lt;code&amp;gt;import readline ; readline.clear_history()&amp;lt;/code&amp;gt;)&lt;br /&gt;
** Prepare the fullchain bundle with &amp;lt;code&amp;gt;cat certificate.pem ca.pem &amp;gt; fullchain.pem&amp;lt;/code&amp;gt;&lt;br /&gt;
** Send a SIGHUP signal to Vault to reload configuration with &amp;lt;code&amp;gt;kill -1 &amp;lt;Vault PID&amp;gt;&amp;lt;/code&amp;gt;, HTTP server should pick new certificate and you can know directly use the vault command. Vault configuration currently uses fullchain.pem and private.key.&lt;br /&gt;
&lt;br /&gt;
CSR uses &amp;lt;code&amp;gt;line1\nline2\nline3&amp;lt;/code&amp;gt; format in JSON. You can use a Python REPL with print(&amp;quot;...&amp;quot;) to print the CSR in several lines. CSR isn&#039;t confidential information, key is protected in Vault and never exposed.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;jq.&#039;&#039;&#039; Another tool that can help is &amp;lt;code&amp;gt;jq&amp;lt;/code&amp;gt;. For example, &amp;lt;code&amp;gt;cat certificate.json | jq -r .data.certificate &amp;gt; /usr/local/etc/certificates/vault/certificate.pem&amp;lt;/code&amp;gt; will save it in multiline format.&lt;br /&gt;
&lt;br /&gt;
If you get an issue about private key missing at Set signed intermediate step, don&#039;t forget you&#039;re setting an intermediate certificate for pki_vault, and not for pki_root, set that here: https://localhost:8200/ui/vault/settings/secrets/configure/pki_vault/cert&lt;br /&gt;
&lt;br /&gt;
Paths where to store certificates matter:&lt;br /&gt;
* pki_root certificates are stored in /usr/local/share/certs&lt;br /&gt;
* pki_vault certificates are stored in /usr/local/etc/certificates/vault&lt;br /&gt;
&lt;br /&gt;
Ensure `private.key` belongs to user `vault` and receives a correct chmod like 400.&lt;br /&gt;
&lt;br /&gt;
==== Services known to break when a certificate is expired ====&lt;br /&gt;
&lt;br /&gt;
* Salt, but that&#039;s ad-hoc and explicit&lt;br /&gt;
* Sentry containers: &amp;lt;code&amp;gt;sudo docker ps -a | grep sentry | grep -v &amp;quot;Up &amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Salt ===&lt;br /&gt;
==== Policy for a node doesn&#039;t contain new secret entry ====&lt;br /&gt;
If the policies are attached to a new role:&lt;br /&gt;
&lt;br /&gt;
# Ensure new secret have been added for the right role in {{Ops file|pillar/credentials/vault.sls}}&lt;br /&gt;
#* If missing, validate afterwards with &amp;lt;code&amp;gt;salt complector pillar.get vault_secrets_by_role:yourrole&amp;lt;/code&amp;gt;&lt;br /&gt;
#* You need to refresh the pillar if still missing: &amp;lt;code&amp;gt;salt complector saltutil.refresh_pillar&amp;lt;/code&amp;gt;&lt;br /&gt;
# Ensure role has been added to {{Ops file|pillar/nodes/nodes.sls}} and NetBox&lt;br /&gt;
#* If missing, refresh pillar afterwards&lt;br /&gt;
#* Validate with &amp;lt;code&amp;gt;salt complector node.get roles &amp;lt;server name&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
# Final check: &amp;lt;code&amp;gt;salt complector state.sls_id salt-node-&amp;lt;server name&amp;gt; roles/vault/policies test=True&amp;lt;/code&amp;gt;&lt;br /&gt;
# If diff is complicated to read, check the full policies document by role: &amp;lt;code&amp;gt;salt complector credentials.build_policies_by_node&amp;lt;/code&amp;gt;&lt;br /&gt;
#* Secret path present? Check the policy isn&#039;t already up-to-date: &amp;lt;code&amp;gt;vault policy read salt-node-&amp;lt;server name&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== credentials.vault_policy_present returns Bad Request ====&lt;br /&gt;
&lt;br /&gt;
Vault returns a 400 error if the policy format is incorrect.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Case 1.&#039;&#039;&#039; The state ID starts by &amp;lt;code&amp;gt;vault_policy_&amp;lt;/code&amp;gt;. You manually added a file to roles/vault/policies/file: this error means Vault API founds a syntax error in it. You can use https://github.com/mschuchard/linter-vault-policy if you use Pulsar (ex Atom) to lint those files.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Case 2.&#039;&#039;&#039; The state ID starts by anything else. The policy has been generated through _modules/credentials.py.&lt;br /&gt;
&lt;br /&gt;
Check if the pillar values added are correct:&lt;br /&gt;
* if not, add a test in &amp;lt;code&amp;gt;_tests/pillar/credentials/test_vault.py&amp;lt;/code&amp;gt; to detect the case&lt;br /&gt;
* if yes, there is an issue with the Python module code to fix&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example of Salt output.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
----------&lt;br /&gt;
          ID: vault_policy_admin&lt;br /&gt;
    Function: credentials.vault_policy_present&lt;br /&gt;
        Name: admin&lt;br /&gt;
      Result: False&lt;br /&gt;
     Comment: Failed to change policy: Bad Request&lt;br /&gt;
     Started: 13:45:14.162421&lt;br /&gt;
    Duration: 76.168 ms&lt;br /&gt;
     Changes:&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Operations grimoire]]&lt;br /&gt;
[[Category:Vault]]&lt;/div&gt;</summary>
		<author><name>Dereckson</name></author>
	</entry>
	<entry>
		<id>https://agora.nasqueron.org/index.php?title=Wearg&amp;diff=2488</id>
		<title>Wearg</title>
		<link rel="alternate" type="text/html" href="https://agora.nasqueron.org/index.php?title=Wearg&amp;diff=2488"/>
		<updated>2026-03-21T09:48:02Z</updated>

		<summary type="html">&lt;p&gt;Dereckson: /* MariaDB server connectivity */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Wearg is an eggdrop and a notifications client.&lt;br /&gt;
&lt;br /&gt;
== Features ==&lt;br /&gt;
&lt;br /&gt;
Wearg handles two important workflows for the Nasqueron Operations SIG:&lt;br /&gt;
&lt;br /&gt;
* Publish notifications on IRC channels: Services --HTTPS--&amp;gt; [[Operations grimoire/Notifications center|Notifications center]] --AMQP--&amp;gt; [[Operations grimoire/RabbitMQ|broker]] --AMQP--&amp;gt; Wearg --IRC--&amp;gt; Channel publication&lt;br /&gt;
* Allow to log to servers log: Channel publication --HTTPS--&amp;gt; Nasqueron API --IO--&amp;gt; servers log&lt;br /&gt;
&lt;br /&gt;
== Troubleshoot ==&lt;br /&gt;
=== No messages are received ===&lt;br /&gt;
Check through another client (the CLI client for example) all works fine at notifications center and broker level.&lt;br /&gt;
&lt;br /&gt;
If so:&lt;br /&gt;
&lt;br /&gt;
# Check we&#039;re connected through &amp;lt;code&amp;gt;.tcl mq connected&amp;lt;/code&amp;gt;&lt;br /&gt;
# If so, disconnect it with &amp;lt;code&amp;gt;.tcl mq disconnect&amp;lt;/code&amp;gt;&lt;br /&gt;
# Check timer through .tcl utimers, you should have one (and only one) timer with ::broker::on_tick as callback&lt;br /&gt;
## Too many timers? kill extra timers with &amp;lt;code&amp;gt;.tcl killutimer timer&amp;lt;id&amp;gt;&amp;lt;/code&amp;gt;, good luck for the guess the second game&lt;br /&gt;
## No timer? &amp;lt;code&amp;gt;.tcl broker::on_tick&amp;lt;/code&amp;gt;&lt;br /&gt;
# Ask next message in the queue .tcl mq get wearg-notifications&lt;br /&gt;
# If stuck at the previous operation, close the connection through the broker interface: http://white-rabbit.nasqueron.org:15672/#/connections (username is daeghrefn, source IP is 212.83.187.132). This method is pretty effective&lt;br /&gt;
&lt;br /&gt;
=== Can&#039;t publish to servers log ===&lt;br /&gt;
==== MariaDB server connectivity ====&lt;br /&gt;
&lt;br /&gt;
If the MariaDB connection is broken, &amp;lt;code&amp;gt;.+log [server] message works&amp;lt;/code&amp;gt;, but not directly &amp;lt;code&amp;gt;[server] message&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* Short-term solution: &amp;lt;code&amp;gt;.tcl sqlrehash&amp;lt;/code&amp;gt; in the Wearg partyline&lt;br /&gt;
* Long-term solution: automate reconnect with {{T|2282}}&lt;/div&gt;</summary>
		<author><name>Dereckson</name></author>
	</entry>
	<entry>
		<id>https://agora.nasqueron.org/index.php?title=Wearg&amp;diff=2487</id>
		<title>Wearg</title>
		<link rel="alternate" type="text/html" href="https://agora.nasqueron.org/index.php?title=Wearg&amp;diff=2487"/>
		<updated>2026-03-21T09:47:30Z</updated>

		<summary type="html">&lt;p&gt;Dereckson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Wearg is an eggdrop and a notifications client.&lt;br /&gt;
&lt;br /&gt;
== Features ==&lt;br /&gt;
&lt;br /&gt;
Wearg handles two important workflows for the Nasqueron Operations SIG:&lt;br /&gt;
&lt;br /&gt;
* Publish notifications on IRC channels: Services --HTTPS--&amp;gt; [[Operations grimoire/Notifications center|Notifications center]] --AMQP--&amp;gt; [[Operations grimoire/RabbitMQ|broker]] --AMQP--&amp;gt; Wearg --IRC--&amp;gt; Channel publication&lt;br /&gt;
* Allow to log to servers log: Channel publication --HTTPS--&amp;gt; Nasqueron API --IO--&amp;gt; servers log&lt;br /&gt;
&lt;br /&gt;
== Troubleshoot ==&lt;br /&gt;
=== No messages are received ===&lt;br /&gt;
Check through another client (the CLI client for example) all works fine at notifications center and broker level.&lt;br /&gt;
&lt;br /&gt;
If so:&lt;br /&gt;
&lt;br /&gt;
# Check we&#039;re connected through &amp;lt;code&amp;gt;.tcl mq connected&amp;lt;/code&amp;gt;&lt;br /&gt;
# If so, disconnect it with &amp;lt;code&amp;gt;.tcl mq disconnect&amp;lt;/code&amp;gt;&lt;br /&gt;
# Check timer through .tcl utimers, you should have one (and only one) timer with ::broker::on_tick as callback&lt;br /&gt;
## Too many timers? kill extra timers with &amp;lt;code&amp;gt;.tcl killutimer timer&amp;lt;id&amp;gt;&amp;lt;/code&amp;gt;, good luck for the guess the second game&lt;br /&gt;
## No timer? &amp;lt;code&amp;gt;.tcl broker::on_tick&amp;lt;/code&amp;gt;&lt;br /&gt;
# Ask next message in the queue .tcl mq get wearg-notifications&lt;br /&gt;
# If stuck at the previous operation, close the connection through the broker interface: http://white-rabbit.nasqueron.org:15672/#/connections (username is daeghrefn, source IP is 212.83.187.132). This method is pretty effective&lt;br /&gt;
&lt;br /&gt;
=== Can&#039;t publish to servers log ===&lt;br /&gt;
==== MariaDB server connectivity ====&lt;br /&gt;
&lt;br /&gt;
If the MariaDB connection is broken, &amp;lt;code&amp;gt;.+log [server] message works&amp;lt;/code&amp;gt;, but not directly &amp;lt;code&amp;gt;[server] message&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Short-term solution: &amp;lt;code&amp;gt;.tcl sqlrehash&amp;lt;/code&amp;gt; in the Wearg partyline&lt;br /&gt;
Long-term solution: {{T|2282}}&lt;/div&gt;</summary>
		<author><name>Dereckson</name></author>
	</entry>
	<entry>
		<id>https://agora.nasqueron.org/index.php?title=Code_conventions&amp;diff=2486</id>
		<title>Code conventions</title>
		<link rel="alternate" type="text/html" href="https://agora.nasqueron.org/index.php?title=Code_conventions&amp;diff=2486"/>
		<updated>2026-03-20T01:47:16Z</updated>

		<summary type="html">&lt;p&gt;Dereckson: /* Makefile */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== All languages ==&lt;br /&gt;
&lt;br /&gt;
* Don&#039;t use more complicated constructs like ternary operators&lt;br /&gt;
* [http://jeroendedauw.github.io/slides/craftmanship/functions/#/1 Keep functions short and simple].&lt;br /&gt;
* Define explicitly methods visibility, as several languages have different default values (e.g. private for C# class members, public for PHP methods)&lt;br /&gt;
* Comments to document a method are written at the singular 3rd person (we seem to have moved to infinitive recently, we need to take a decision here)&lt;br /&gt;
&lt;br /&gt;
== C ==&lt;br /&gt;
If you use [http://clang.llvm.org/docs/ClangFormat.html ClangFormat], a [https://github.com/dereckson/rabbitmq-tcl/blob/master/.clang-format .clang-format file] is available.&lt;br /&gt;
&lt;br /&gt;
== JavaScript ==&lt;br /&gt;
The following conventions are used:&lt;br /&gt;
* K&amp;amp;R, 1TBS variant, including for functions&lt;br /&gt;
* 4 spaces as indent&lt;br /&gt;
* Use modern JavaScript idioms like &amp;lt;code&amp;gt;const&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;let&amp;lt;/code&amp;gt; instead of &amp;lt;code&amp;gt;var&amp;lt;/code&amp;gt;&lt;br /&gt;
* Consider to use async code for events-driven development, especially for servers&lt;br /&gt;
&lt;br /&gt;
== PHP ==&lt;br /&gt;
The following conventions are used:&lt;br /&gt;
* K&amp;amp;R, 1TBS variant, including for functions&lt;br /&gt;
* 4 spaces as indent&lt;br /&gt;
* The keywords &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;null&amp;lt;/code&amp;gt; must be in lower case.&lt;br /&gt;
* Arrays use short syntax&lt;br /&gt;
* Array elements ends with a comma&lt;br /&gt;
* Functions, methods and class names use camel case &lt;br /&gt;
&lt;br /&gt;
If you use PhpStorm or another JetBrains IDE, you can import [https://github.com/nasqueron/codestyle/blob/master/JetBrains/php-codestyle.xml JetBrains/php-codestyle.xml] from the codestyle repository as a code style (Settings or Default Settings &amp;gt; Editor &amp;gt; Code Style &amp;gt; PHP &amp;gt; click on the wheel icon &amp;gt; Import Scheme &amp;gt; Intellij IDEA codestyle XML).&lt;br /&gt;
&lt;br /&gt;
If you want to lint a project with phpcs, you can require the Composer package &amp;lt;code&amp;gt;nasqueron/codestyle&amp;lt;/code&amp;gt; and use the following &amp;lt;kbd&amp;gt;phpcs.xml&amp;lt;kbd&amp;gt; standard file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;ruleset&amp;gt;&lt;br /&gt;
    &amp;lt;rule ref=&amp;quot;vendor/nasqueron/codestyle/CodeSniffer&amp;quot; /&amp;gt;&lt;br /&gt;
    &amp;lt;file&amp;gt;.&amp;lt;/file&amp;gt;&lt;br /&gt;
    &amp;lt;exclude-pattern&amp;gt;\.git/&amp;lt;/exclude-pattern&amp;gt;&lt;br /&gt;
    &amp;lt;exclude-pattern&amp;gt;vendor/&amp;lt;/exclude-pattern&amp;gt;&lt;br /&gt;
&amp;lt;/ruleset&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Python ==&lt;br /&gt;
=== Code style ===&lt;br /&gt;
&#039;&#039;&#039;2023.&#039;&#039;&#039; We follow [https://black.readthedocs.io/en/stable/the_black_code_style/current_style.html black style], so use black utility (&amp;lt;code&amp;gt;pip install black&amp;lt;/code&amp;gt;). As such, you need to configure Flake8 to ignore rule E203.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;2015.&#039;&#039;&#039; We follow [https://www.python.org/dev/peps/pep-0008/ PEP-8].&lt;br /&gt;
&lt;br /&gt;
=== Templates ===&lt;br /&gt;
A template exists for a new Python command: [https://devcentral.nasqueron.org/source/snippets/browse/main/python/command.py python/command.py]&lt;br /&gt;
&lt;br /&gt;
In packages, empty __init__.py files can follow [https://devcentral.nasqueron.org/source/merge-dictionaries/browse/main/src/mergedictionaries/utils/__init__.py;eaf5bc2c21118454837e8148147606c19d4afff7 this example].&lt;br /&gt;
&lt;br /&gt;
=== Configuration files ===&lt;br /&gt;
Allow empty configuration files. For example, the YAML parser will return None if the file exists but is empty, we can catch that and return default instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
         with open(get_configuration_path()) as fd:&lt;br /&gt;
            return yaml.safe_load(fd) or {}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Rust ==&lt;br /&gt;
&#039;&#039;&#039;2023.&#039;&#039;&#039; Automated codestyle (black in Python, clang-format in Rust) seems preferable. As such, a style compatible with &amp;lt;code&amp;gt;rustfmt&amp;lt;/code&amp;gt; is needed to be able to format using &amp;lt;code&amp;gt;cargo fmt&amp;lt;/code&amp;gt;. You can add to your project  [https://devcentral.nasqueron.org/source/codestyle/browse/main/rust/rustfmt.toml rust/rustfmt.toml in codestyle] to configure it.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;2015.&#039;&#039;&#039; We followed &amp;quot;Rust default style&amp;quot;, described at [https://web.archive.org/web/20170320083740/http://aturon.github.io/ https://aturon.github.io/]. It&#039;s mainly a K&amp;amp;R, 1TBS variant.&lt;br /&gt;
&lt;br /&gt;
Use trailing comma for elements in every struct/impl/etc.&lt;br /&gt;
&lt;br /&gt;
=== Threads ===&lt;br /&gt;
Standard library isn&#039;t the most ergonomic for threads programming, those crate allows more efficient and legible code:&lt;br /&gt;
* [https://docs.rs/crossbeam-channel/latest/crossbeam_channel/ crossbeam_channel] for mpmc (multiple producers, multiple consumers)&lt;br /&gt;
* [https://docs.rs/parking_lot/latest/parking_lot/type.Mutex.html parking_lot] for Mutex&lt;br /&gt;
&lt;br /&gt;
== Salt ==&lt;br /&gt;
=== Style ===&lt;br /&gt;
Whitespaces:&lt;br /&gt;
* Indent with two spaces&lt;br /&gt;
* YAML lists use indented bullets&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;yaml&amp;quot;&amp;gt;&lt;br /&gt;
id:&lt;br /&gt;
  method:&lt;br /&gt;
    - somekey: value&lt;br /&gt;
    - otherkey: value&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Tips ===&lt;br /&gt;
&lt;br /&gt;
;Files provisioned&lt;br /&gt;
* When you ask to download a file remotely, you need a source hash, pick SHA256 as algo&lt;br /&gt;
* Each file provisioned from the Salt repository must contains an header explaining the fact, with the full path in the rOPS repo&lt;br /&gt;
&lt;br /&gt;
;BSD and Linux distros compatible states&lt;br /&gt;
* populate the map.jinja file with OS logic (e.g. `dirs` for /etc vs /usr/local/etc)&lt;br /&gt;
* when you&#039;ve a specific set of tasks to do for one OS/distro, it&#039;s acceptable to enclose it in a state by an if block&lt;br /&gt;
&lt;br /&gt;
=== Vocabulary ===&lt;br /&gt;
&lt;br /&gt;
;Domain names&lt;br /&gt;
:To refer to the fully qualified domain name sub.domain.tld, use &#039;&#039;&#039;fqdn&#039;&#039;&#039;. To split the domains in part, use &#039;&#039;&#039;domain&#039;&#039;&#039; and &#039;&#039;&#039;subdomain&#039;&#039;&#039;. This is important to understand a state without having  to refer to the associated pillar to disambig domain.&lt;br /&gt;
&lt;br /&gt;
== Shell scripts ==&lt;br /&gt;
;UNIX agnosticism:&lt;br /&gt;
* Don&#039;t assume absolute path, use &amp;lt;code&amp;gt;#!/usr/bin/env bash&amp;lt;/code&amp;gt; and not &amp;lt;code&amp;gt;#!/bin/bash&amp;lt;/code&amp;gt; (it could be elsewhere on BSD or Solaris)&lt;br /&gt;
* Use `sh` as must as possible, try to avoid &amp;lt;code&amp;gt;bash&amp;lt;/code&amp;gt;, document exceptions rationale in your commits&lt;br /&gt;
&lt;br /&gt;
;Whitespaces:&lt;br /&gt;
* One whitespace line between shebang and actual content&lt;br /&gt;
* 4 spaces as indent&lt;br /&gt;
&lt;br /&gt;
;File names:&lt;br /&gt;
* We use hyphens (-) as separators, not underscores or camelcase&lt;br /&gt;
* Filename should start by a verb if it performs an action&lt;br /&gt;
* Don&#039;t use .sh extensions when deployed as command&lt;br /&gt;
** sometimes you&#039;ll see them on Phabricator pastes&#039; titles, but it has been added there, so Phab knows shell syntax highlighting should be used&lt;br /&gt;
** &#039;&#039;&#039;Tip.&#039;&#039;&#039; You can use .sh in src/ to help linters, but then provide a Makefile to install it under correct name without extension. Same for operations repository where everything uses .sh, but when deploying with file.managed the extension is omitted&lt;br /&gt;
&lt;br /&gt;
;Templates&lt;br /&gt;
* New command: [https://devcentral.nasqueron.org/source/snippets/browse/main/shell/script.sh shell/script.sh]&lt;br /&gt;
&lt;br /&gt;
== TCL ==&lt;br /&gt;
&lt;br /&gt;
* Indent with 4 spaces, as of 2026-03-20&lt;br /&gt;
* Keep blocks visually separated&lt;br /&gt;
* Use Tcl primitives instead of manual parsing for strings: split, lindex, lrange, join&lt;br /&gt;
* Avoid regex unless necessary&lt;br /&gt;
* List expansion {*} instead of eval&lt;br /&gt;
&lt;br /&gt;
; ViperServ development&lt;br /&gt;
* If you build a full new system, all procedures must be defined in a namespace&lt;br /&gt;
* Use fully-qualified names (::namespace::proc) for procedure definitions and cross-namespace calls&lt;br /&gt;
* Separate low-level request logic from API-specific methods&lt;br /&gt;
&lt;br /&gt;
== Makefile ==&lt;br /&gt;
UNIX agnosticism:&lt;br /&gt;
* Test your makefile against BSD make, and document in README.md to use GNU Makefile (gmake) when it&#039;s not convenient to keep compatibility&lt;br /&gt;
&lt;br /&gt;
Presentation:&lt;br /&gt;
* Create a block with the general targets, then sections with your targets organized by categories/goals/parts&lt;br /&gt;
&lt;br /&gt;
Tip:&lt;br /&gt;
* It&#039;s possible to provision BSDmakefile and GNUmakefile when UNIX agnosticism doesn&#039;t work.&lt;br /&gt;
&lt;br /&gt;
== Structured data formats (YAML, JSON, XML) ==&lt;br /&gt;
The number of spaces depend if the format is usually heavily hierarchized or not:&lt;br /&gt;
&lt;br /&gt;
* 2 spaces for JSON and YAML&lt;br /&gt;
* 4 spaces for XML, TOML and other configuration files&lt;br /&gt;
&lt;br /&gt;
== Utilities ==&lt;br /&gt;
&lt;br /&gt;
The https://github.com/nasqueron/codestyle repository contains resource to help to respect code convention, like a phpcs ruleset, a configuration ready for PhpStorm, IntelliJ and other JetBrains editors, or a clang-format configuration file.&lt;br /&gt;
&lt;br /&gt;
== Troubleshoot ==&lt;br /&gt;
=== Fix indent issues ===&lt;br /&gt;
The &amp;lt;code&amp;gt;expand&amp;lt;/code&amp;gt; utility converts tabs into spaces, while &amp;lt;code&amp;gt;unexpand&amp;lt;/code&amp;gt; convert spaces into tabs.&lt;br /&gt;
&lt;br /&gt;
Switch a file from tab indent to 4 spaces indent:&lt;br /&gt;
&lt;br /&gt;
    $ expand -t 4 foo.sh &amp;gt; a&lt;br /&gt;
    $ cat a &amp;gt; foo.sh&lt;br /&gt;
    $ rm a&lt;br /&gt;
&lt;br /&gt;
(Avoid &amp;lt;code&amp;gt;mv&amp;lt;/code&amp;gt; for shell scripts as your foo.sh has probably a 755 chmod, and a will probably have a 644 chmod, assuming 022 as umask)&lt;br /&gt;
&lt;br /&gt;
Switch a file indent with 2 spaces to 4 spaces:&lt;br /&gt;
&lt;br /&gt;
    $ unexpand -t 2 JetBrains/php-codestyle.xml &amp;gt; a&lt;br /&gt;
    $ expand -t 4 a &amp;gt; JetBrains/php-codestyle.xml&lt;br /&gt;
&lt;br /&gt;
This last technique can be used in batch [https://gist.github.com/dereckson/80a746b408c0cf0b688a09db31d5c881 with this reindent script]:&lt;br /&gt;
&lt;br /&gt;
    $ git ls-files | xargs -n1 reindent 2 4 &lt;br /&gt;
&lt;br /&gt;
[[Category:Reference]]&lt;br /&gt;
[[Category:Contributor guide]]&lt;/div&gt;</summary>
		<author><name>Dereckson</name></author>
	</entry>
	<entry>
		<id>https://agora.nasqueron.org/index.php?title=Clean_up&amp;diff=2485</id>
		<title>Clean up</title>
		<link rel="alternate" type="text/html" href="https://agora.nasqueron.org/index.php?title=Clean_up&amp;diff=2485"/>
		<updated>2026-03-20T01:38:43Z</updated>

		<summary type="html">&lt;p&gt;Dereckson: /* Tab to spaces */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Style ==&lt;br /&gt;
=== EOL at EOF ===&lt;br /&gt;
There is a need for a blank line at end of file.&lt;br /&gt;
&lt;br /&gt;
You can add them with &amp;lt;code&amp;gt;echo&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;&lt;br /&gt;
$ git ls-files | while read f; do tail -n1 $f | read -r _ || echo &amp;gt;&amp;gt; $f; done&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== UNIX lines ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;&lt;br /&gt;
$ dos2unix&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Encoding ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;&lt;br /&gt;
$ iconv -f iso-8859-15 -t utf-8&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Tab to spaces ===&lt;br /&gt;
Git has a filter to be able to normalize with expand. See [https://eev.ee/blog/2016/06/04/converting-a-git-repo-from-tabs-to-spaces/ here].&lt;br /&gt;
&lt;br /&gt;
As expand doesn&#039;t have a inline capability, you need to create a temporary file:&lt;br /&gt;
&lt;br /&gt;
    tmp_file=$(mktemp -t spaces)&lt;br /&gt;
    expand -t 4 &amp;quot;$source_file&amp;quot; &amp;gt; &amp;quot;$tmp_file&amp;quot;&lt;br /&gt;
    mv &amp;quot;$tmp_file&amp;quot; &amp;quot;$source_file&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== Trailing spaces ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;&lt;br /&gt;
$ git ls-files | xargs -n 1 gsed -i &#039;s/[[:space:]]*$//&#039;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== UTF-8 BOM ===&lt;br /&gt;
Some old editors started a file by the sequence of bytes [0xEF, 0xBB, 0xBF] to allow the UTF-8 file encoding to be detected. This practice is discouraged nowadays and those should removed.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;&lt;br /&gt;
$ sed -e &#039;1s/^\xef\xbb\xbf//&#039; &amp;lt; bomfile &amp;gt; newfile&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Howto]]&lt;br /&gt;
[[Category:Contributor guide]]&lt;/div&gt;</summary>
		<author><name>Dereckson</name></author>
	</entry>
	<entry>
		<id>https://agora.nasqueron.org/index.php?title=WindRiver&amp;diff=2484</id>
		<title>WindRiver</title>
		<link rel="alternate" type="text/html" href="https://agora.nasqueron.org/index.php?title=WindRiver&amp;diff=2484"/>
		<updated>2026-03-19T22:23:05Z</updated>

		<summary type="html">&lt;p&gt;Dereckson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;WindRiver is an FreeBSD 14 bare metal server for Nasqueron general-purpose development.&lt;br /&gt;
&lt;br /&gt;
It supersedes [[Ysul]].&lt;br /&gt;
&lt;br /&gt;
Documentation: [[Devserver reference]]&lt;br /&gt;
&lt;br /&gt;
== Basic information ==&lt;br /&gt;
* &#039;&#039;&#039;IP:&#039;&#039;&#039;&lt;br /&gt;
** 195.154.30.15 &amp;lt;strike&amp;gt;51.159.17.168 since 2023-06-14. Previously 51.159.18.59.&amp;lt;/strike&amp;gt;&lt;br /&gt;
** 2a02:578:4f0d:0:30d0:7b22:6cde:a52e (native, still to migrate)&lt;br /&gt;
** 2001:bc8:6005:5:aa1e:84ff:fef3:5d9c (future through HE)&lt;br /&gt;
* &#039;&#039;&#039;Hostname:&#039;&#039;&#039; windriver.nasqueron.org&lt;br /&gt;
* &#039;&#039;&#039;Homepage:&#039;&#039;&#039; https://windriver.nasqueron.org/&lt;br /&gt;
* &#039;&#039;&#039;Configuration:&#039;&#039;&#039; &amp;lt;strike&amp;gt;64 Gb RAM, Xeon E3 1240 V6, 2x 500 GB SSD (&amp;quot;Pro-6-S&amp;quot;)&amp;lt;/strike&amp;gt; 96 Gb. RAM, Xeon E5-1650 v3, 3x 500 GB SSD (&amp;quot;Pro-4-L&amp;quot;)&lt;br /&gt;
* &#039;&#039;&#039;ISP:&#039;&#039;&#039; [http://www.online.net Online] (FR)&lt;br /&gt;
* &#039;&#039;&#039;Network:&#039;&#039;&#039; Illiad (FR)&lt;br /&gt;
* &#039;&#039;&#039;Policy:&#039;&#039;&#039; Access for any Nasqueron project and for infrastructure operations task.&lt;br /&gt;
* &#039;&#039;&#039;Started:&#039;&#039;&#039; 2019-11-21&lt;br /&gt;
&lt;br /&gt;
== Ports ==&lt;br /&gt;
&lt;br /&gt;
Ports for services managed automatically through Salt are available on {{Ops file|PORTS}}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Reserved ports - IRC server range&lt;br /&gt;
|-&lt;br /&gt;
! Port !! User account !! Description&lt;br /&gt;
|-&lt;br /&gt;
| 6901 || dereckson || irssi proxy&lt;br /&gt;
|-&lt;br /&gt;
| 6902 || dereckson || irssi proxy&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Dereckson</name></author>
	</entry>
	<entry>
		<id>https://agora.nasqueron.org/index.php?title=User:Dereckson/Devserver&amp;diff=2483</id>
		<title>User:Dereckson/Devserver</title>
		<link rel="alternate" type="text/html" href="https://agora.nasqueron.org/index.php?title=User:Dereckson/Devserver&amp;diff=2483"/>
		<updated>2026-03-19T22:02:12Z</updated>

		<summary type="html">&lt;p&gt;Dereckson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== MediaWiki ==&lt;br /&gt;
=== Logs ===&lt;br /&gt;
tail -n 100 -f /var/log/www/dereckson.be/mediawiki-php.log&lt;br /&gt;
&lt;br /&gt;
=== Reinstall ===&lt;br /&gt;
* /var/51-wwwroot/mediawiki-dereckson/core: wikimedia/core repository&lt;br /&gt;
* /var/51-wwwroot/mediawiki-dereckson/core/extensions: symlink to &amp;lt;code&amp;gt;../extensions&amp;lt;/code&amp;gt;&lt;br /&gt;
** Clone all needed extensions in /var/51-wwwroot/mediawiki-dereckson/extensions&lt;br /&gt;
* /var/51-wwwroot/mediawiki-dereckson/core/skins: symlink to &amp;lt;code&amp;gt;../skins&amp;lt;/code&amp;gt;&lt;br /&gt;
** Same with git clone ssh://review/mediawiki/skins/&lt;br /&gt;
* /var/dataroot/mediawiki.dereckson.be/data contains:&lt;br /&gt;
** my_wiki.sqlite for the content&lt;br /&gt;
** wikicache.sqlite for the cache&lt;br /&gt;
&lt;br /&gt;
=== Update ===&lt;br /&gt;
* &#039;&#039;&#039;Core:&#039;&#039;&#039; mw-update-core (currently writing it)&lt;br /&gt;
&lt;br /&gt;
=== Create a new extension ===&lt;br /&gt;
;I. Wikimedia side&lt;br /&gt;
* [[mw:Manual:Developing_extensions]] &lt;br /&gt;
* [[mw:Gerrit/New repositories/Requests]]&lt;br /&gt;
* [https://phabricator.wikimedia.org/maniphest/task/edit/form/1/?projects=Project-Admins Create task for new Phabricator project]&lt;br /&gt;
&lt;br /&gt;
;II. WindRiver&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;shell&amp;quot;&amp;gt;&lt;br /&gt;
$ setenv MW_EXTENSION foo&lt;br /&gt;
$ cd ~/dev/wikimedia/mediawiki/extensions&lt;br /&gt;
$ git clone ssh://review/mediawiki/extensions/$MW_EXTENSION || git init $MW_EXTENSION &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Extension is actually stored at /var/51-wwwroot/mediawiki-dereckson/extensions, so can immediately be configured to test locally.&lt;br /&gt;
&lt;br /&gt;
;III. SaaS deployment&lt;br /&gt;
* {{Ops file|pillar/saas/mediawiki.sls}}&lt;br /&gt;
* [https://devcentral.nasqueron.org/source/saas-mediawiki/browse/main/config/Settings.php config/Settings.php]&lt;br /&gt;
&lt;br /&gt;
=== Troubleshoot ===&lt;br /&gt;
==== SQLite database is read-only ====&lt;br /&gt;
Runtime error near line 2: attempt to write a readonly database (8)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;shell&amp;quot;&amp;gt;&lt;br /&gt;
chown -R web-be-dereckson-mw:dereckson /var/dataroot/mediawiki.dereckson.be/data&lt;br /&gt;
chmod 771 /var/dataroot/mediawiki.dereckson.be/data&lt;br /&gt;
chmod 660 /var/dataroot/mediawiki.dereckson.be/data/my_wiki.sqlite&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Permissions to run tests and maintenance scripts ===&lt;br /&gt;
To run tests against wiki and maintenance scripts as user can be tricky:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;shell&amp;quot;&amp;gt;&lt;br /&gt;
touch /tmp/mw-GlobalIdGenerator5001-UID-nodeid /tmp/mw-GlobalIdGenerator5001-UUID-128&lt;br /&gt;
chown web-be-dereckson-mw:dereckson /tmp/mw-GlobalIdGenerator5001-*&lt;br /&gt;
chmod 664 /tmp/mw-GlobalIdGenerator5001-*&lt;br /&gt;
&lt;br /&gt;
chmod 771 /var/dataroot/mediawiki.dereckson.be/data/locks&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Zed ==&lt;br /&gt;
=== Logs ===&lt;br /&gt;
tail -n 100 -f /var/log/www/dereckson.be/zed51-php.log&lt;br /&gt;
&lt;br /&gt;
=== Staging  ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note. Keruald is currently symlinked from the monorepo to vendor/keruald.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
To recreate Zed staging area:&lt;br /&gt;
&lt;br /&gt;
    $ cd /var/dataroot/zed/content&lt;br /&gt;
    $ git init .&lt;br /&gt;
    $ git config --global --add safe.directory /var/dataroot/zed/content&lt;br /&gt;
    $ git remote add origin git@github.com:hypership/content.git&lt;br /&gt;
    $ git fetch --all&lt;br /&gt;
    $ git reset --hard origin/main&lt;br /&gt;
    $ git clone git@github.com:hypership/content_users.git users&lt;br /&gt;
    &lt;br /&gt;
    $ sudo -u web-be-dereckson-zed51 mkdir /var/dataroot/zed/cache/sessions&lt;br /&gt;
    $ sudo mkdir -p /var/dataroot/zed/content/users/_photos/tn&lt;br /&gt;
    $ sudo chown -R web-be-dereckson-zed51:dereckson /var/dataroot/zed/content/users/_photos&lt;br /&gt;
    $ sudo chmod 771 /var/dataroot/zed/content/users/_photos /var/dataroot/zed/content/users/_photos/tn&lt;br /&gt;
    &lt;br /&gt;
    $ mkdir -p /home/dereckson/dev/zed/hypership&lt;br /&gt;
    $ cd /home/dereckson/dev/zed/hypership&lt;br /&gt;
    $ ln -s /var/dataroot/zed/content&lt;br /&gt;
    &lt;br /&gt;
Note: Zed currently not defined in wwwroot-51 in rOPS, should be done for /var/51-wwwroot/zed&lt;br /&gt;
&lt;br /&gt;
== IRC ==&lt;br /&gt;
&lt;br /&gt;
=== Troubleshoot ===&lt;br /&gt;
==== Error loading module proxy/irc ====&lt;br /&gt;
When trying to load proxy module, I got:&lt;br /&gt;
&lt;br /&gt;
    22:00:09 -!- Irssi: Error loading module proxy/irc: /home/dereckson/.irssi/modules/libirc_proxy.so: Undefined symbol &amp;quot;g_input_add&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Proxy is now compiled by default, personal module needs to be deleted.&lt;/div&gt;</summary>
		<author><name>Dereckson</name></author>
	</entry>
</feed>