<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Reliability-Security on StackOnward</title><link>https://stackonward.com/topics/reliability-security/</link><description>Recent content in Reliability-Security on StackOnward</description><generator>Hugo</generator><language>en-US</language><lastBuildDate>Fri, 11 Sep 2026 12:00:00 +0800</lastBuildDate><atom:link href="https://stackonward.com/topics/reliability-security/index.xml" rel="self" type="application/rss+xml"/><item><title>Go Live with Payments: From Sandbox Keys to the First Real Order</title><link>https://stackonward.com/posts/payment-sandbox-to-production-launch/</link><pubDate>Fri, 11 Sep 2026 05:24:00 +0800</pubDate><guid>https://stackonward.com/posts/payment-sandbox-to-production-launch/</guid><description>&lt;p&gt;The checkout page already uses a live key, but the subscription still cites a test Price. After the customer pays, the production webhook fails signature checks because it still uses the sandbox secret. Mixed config does not fail together: some errors stop before payment, others wait until money has moved, then order, entitlements, and finance stop in different states.&lt;/p&gt;
&lt;p&gt;The cutover order is: fence entries that create captures and refunds; attach account, keys, Price, webhook, domain, workers, and finance to live together; use read-only requests, test events, and return-URL checks to catch environment errors; then open the first real order under provider rules. If that first order fails, close new transactions. Webhooks, lookups, and reconciliation keep running.&lt;/p&gt;</description></item><item><title>How to Configure Docker Volume Permissions and Secrets</title><link>https://stackonward.com/posts/docker-volume-permissions-secrets/</link><pubDate>Fri, 11 Sep 2026 05:12:00 +0800</pubDate><guid>https://stackonward.com/posts/docker-volume-permissions-secrets/</guid><description>&lt;p&gt;How to configure Docker volume permissions starts with a numeric UID and GID match, not a matching username. Put database files and other container-generated state on a named volume, bind-mount host-managed config read-only, and grant each secret only to the service that reads it as a file. Recreate the container to prove the mount. Restore a backup in a separate environment to prove the backup.&lt;/p&gt;
&lt;figure&gt;
 &lt;img src="https://stackonward.com/images/posts/docker-volume-permissions-secrets/en/storage-boundaries.svg" alt="An application container writes database state to a named volume, reads host config read-only, and reads a password from a granted secret file" loading="lazy" decoding="async"&gt;
 &lt;figcaption&gt;Named volumes hold writable state. Bind mounts hold host-managed config. Secret files are granted per service.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h2 id="choose-a-named-volume-bind-mount-or-tmpfs"&gt;Choose a named volume, bind mount, or tmpfs&lt;/h2&gt;
&lt;div class="table-responsive" role="region" aria-label="Scrollable table" tabindex="0"&gt;
 &lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Type&lt;/th&gt;
					&lt;th&gt;What belongs there&lt;/th&gt;
					&lt;th&gt;Why&lt;/th&gt;
					&lt;th&gt;Main risk&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;Named volume&lt;/td&gt;
					&lt;td&gt;Databases, queues, application state&lt;/td&gt;
					&lt;td&gt;Docker manages the lifecycle; the path is not tied to one host layout&lt;/td&gt;
					&lt;td&gt;Host backup and migration must name the volume and its driver&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Bind mount&lt;/td&gt;
					&lt;td&gt;Caddyfile, explicit data directories, host scripts&lt;/td&gt;
					&lt;td&gt;The path is visible to existing backup and permission tools&lt;/td&gt;
					&lt;td&gt;The host path, owner, and SELinux or AppArmor labels all have to match&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;tmpfs&lt;/td&gt;
					&lt;td&gt;Short-lived sensitive files or fast scratch data that must not persist&lt;/td&gt;
					&lt;td&gt;Nothing is written to durable disk&lt;/td&gt;
					&lt;td&gt;A restart drops the files; the size counts against container memory&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://docs.docker.com/engine/storage/" target="_blank" rel="noopener"&gt;Docker storage&lt;span class="sr-only"&gt;(opens in a new tab)&lt;/span&gt;&lt;/a&gt; treats &lt;a href="https://docs.docker.com/engine/storage/volumes/" target="_blank" rel="noopener"&gt;volumes&lt;span class="sr-only"&gt;(opens in a new tab)&lt;/span&gt;&lt;/a&gt; as the default for data a container generates. &lt;a href="https://docs.docker.com/engine/storage/bind-mounts/" target="_blank" rel="noopener"&gt;Bind mounts&lt;span class="sr-only"&gt;(opens in a new tab)&lt;/span&gt;&lt;/a&gt; are for files the host already owns. &lt;a href="https://docs.docker.com/engine/storage/tmpfs/" target="_blank" rel="noopener"&gt;tmpfs&lt;span class="sr-only"&gt;(opens in a new tab)&lt;/span&gt;&lt;/a&gt; stays in host memory and is gone when the container stops. The image writable layer is the wrong place for runtime data: deleting the container deletes that layer.&lt;/p&gt;</description></item><item><title>How to Expose Docker Ports: 127.0.0.1, 0.0.0.0, Firewalls</title><link>https://stackonward.com/posts/docker-port-firewall-loopback/</link><pubDate>Fri, 11 Sep 2026 04:14:00 +0800</pubDate><guid>https://stackonward.com/posts/docker-port-firewall-loopback/</guid><description>&lt;p&gt;How to expose Docker ports depends on the process listen address inside the container, the host publish bind, and the firewall or cloud security group in front of the host. Listening on &lt;code&gt;0.0.0.0&lt;/code&gt; inside a container does not put that port on the public internet.&lt;/p&gt;
&lt;figure&gt;
 &lt;img src="https://stackonward.com/images/posts/docker-port-firewall-loopback/en/network-boundaries.svg" alt="Public traffic crosses a cloud security group and host firewall to a reverse proxy; the app and database talk only on the Docker network" loading="lazy" decoding="async"&gt;
 &lt;figcaption&gt;The app and database stay on the Docker network. The public internet reaches only the ports the proxy publishes.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h2 id="how-to-expose-docker-ports-at-each-network-layer"&gt;How to expose Docker ports at each network layer&lt;/h2&gt;
&lt;div class="table-responsive" role="region" aria-label="Scrollable table" tabindex="0"&gt;
 &lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Where it is set&lt;/th&gt;
					&lt;th&gt;Example&lt;/th&gt;
					&lt;th&gt;What it means&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;App process listen&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;0.0.0.0:8080&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Accept 8080 on every interface in this container&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;App process listen&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;127.0.0.1:8080&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Accept 8080 only on this container’s loopback&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Docker port publish&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;127.0.0.1:8080:8080&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Host-local processes can reach container 8080 on host 8080&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Docker port publish&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;0.0.0.0:8080:8080&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Every IPv4 address on the host publishes 8080; the public internet may reach it&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Compose internal access&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;http://app:8080&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;A peer on the same network uses the service name and the container port&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;

&lt;/div&gt;

&lt;p&gt;The two uses of &lt;code&gt;0.0.0.0&lt;/code&gt; are not the same action. Listening on every interface inside the container lets a proxy on the same Docker network connect. Publishing the port onto every host interface widens the host entry.&lt;/p&gt;</description></item></channel></rss>