Skip to content

Commit ce703eb

Browse files
committed
Updates
1 parent bb9e950 commit ce703eb

7 files changed

Lines changed: 254 additions & 5 deletions

File tree

astro.config.mjs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,14 @@ export default defineConfig({
364364
{ label: 'Client', link: 'aspire/orleans/client' }
365365
]
366366
},
367+
{
368+
label: 'Gluetun VPN',
369+
items:[
370+
{ label: 'Getting Started', link: 'aspire/gluetun/' },
371+
{ label: 'Configuration', link: 'aspire/gluetun/configuration' },
372+
{ label: 'Container Routing', link: 'aspire/gluetun/routing' }
373+
]
374+
},
367375
{ label: 'Release Notes', link: 'aspire/release-notes' }
368376
]
369377
}
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
---
2+
title: Configuration
3+
description: VPN provider, server selection, proxy, and firewall configuration for Gluetun
4+
---
5+
import NugetBadge from '/src/components/NugetBadge.tsx';
6+
7+
<NugetBadge name="Shiny.Aspire.Hosting.Gluetun" showLabel={true} />
8+
9+
## VPN Provider
10+
11+
Every Gluetun setup requires a VPN service provider:
12+
13+
```csharp
14+
var vpn = builder.AddGluetun("vpn")
15+
.WithVpnProvider("mullvad");
16+
```
17+
18+
See the [Gluetun wiki](https://github.com/qdm12/gluetun-wiki) for the full list of supported providers.
19+
20+
## VPN Protocol
21+
22+
### WireGuard
23+
24+
```csharp
25+
// String key (for development/testing)
26+
vpn.WithWireGuard("my-private-key");
27+
28+
// Aspire parameter resource (recommended for secrets)
29+
vpn.WithWireGuard(builder.AddParameter("wireguard-key", secret: true));
30+
```
31+
32+
Sets `VPN_TYPE=wireguard` and `WIREGUARD_PRIVATE_KEY`.
33+
34+
### OpenVPN
35+
36+
```csharp
37+
// String credentials (for development/testing)
38+
vpn.WithOpenVpn("username", "password");
39+
40+
// Aspire parameter resources (recommended for secrets)
41+
vpn.WithOpenVpn(
42+
builder.AddParameter("openvpn-user"),
43+
builder.AddParameter("openvpn-pass", secret: true));
44+
```
45+
46+
Sets `VPN_TYPE=openvpn`, `OPENVPN_USER`, and `OPENVPN_PASSWORD`.
47+
48+
## Server Selection
49+
50+
```csharp
51+
vpn.WithServerCountries("US", "Canada", "Germany");
52+
vpn.WithServerCities("New York", "Toronto");
53+
```
54+
55+
Values are comma-joined and set as `SERVER_COUNTRIES` / `SERVER_CITIES` environment variables.
56+
57+
## Proxy Features
58+
59+
Gluetun includes built-in HTTP and Shadowsocks proxies:
60+
61+
```csharp
62+
vpn.WithHttpProxy(); // HTTPPROXY=on
63+
vpn.WithHttpProxy(false); // HTTPPROXY=off
64+
vpn.WithShadowsocks(); // SHADOWSOCKS=on
65+
vpn.WithShadowsocks(false); // SHADOWSOCKS=off
66+
```
67+
68+
To expose the proxy ports, pass them when creating the resource:
69+
70+
```csharp
71+
var vpn = builder.AddGluetun("vpn", httpProxyPort: 8888, shadowsocksPort: 8388)
72+
.WithHttpProxy()
73+
.WithShadowsocks();
74+
```
75+
76+
## Network & Firewall
77+
78+
```csharp
79+
vpn.WithFirewallOutboundSubnets("10.0.0.0/8", "192.168.0.0/16");
80+
vpn.WithTimezone("America/New_York");
81+
```
82+
83+
`WithFirewallOutboundSubnets` sets `FIREWALL_OUTBOUND_SUBNETS`, useful for allowing traffic to local network resources outside the VPN tunnel.
84+
85+
## Generic Environment Variables
86+
87+
For any Gluetun environment variable not covered by the typed methods:
88+
89+
```csharp
90+
// String value
91+
vpn.WithGluetunEnvironment("DNS_ADDRESS", "1.1.1.1");
92+
93+
// Aspire parameter resource
94+
vpn.WithGluetunEnvironment("UPDATER_PERIOD", builder.AddParameter("updater-period"));
95+
```
96+
97+
This is useful for provider-specific settings. See the [Gluetun wiki](https://github.com/qdm12/gluetun-wiki) for the full list of environment variables.
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
---
2+
title: Getting Started
3+
description: Aspire hosting integration for Gluetun VPN containers
4+
---
5+
import NugetBadge from '/src/components/NugetBadge.tsx';
6+
import { Steps } from '@astrojs/starlight/components';
7+
8+
Aspire hosting integration for [Gluetun](https://github.com/qdm12/gluetun), a lightweight VPN client container supporting 30+ providers. Models Gluetun as a first-class Aspire resource and lets other containers route their traffic through the VPN tunnel.
9+
10+
- [GitHub Repository](https://github.com/shinyorg/aspire)
11+
- [Gluetun Wiki](https://github.com/qdm12/gluetun-wiki)
12+
13+
## Package
14+
15+
| Package | NuGet |
16+
|---|---|
17+
| Aspire AppHost | <NugetBadge name="Shiny.Aspire.Hosting.Gluetun" showLabel={true} /> |
18+
19+
## Features
20+
21+
- **First-class Aspire resource** — Gluetun VPN container with `NET_ADMIN` capability and `/dev/net/tun` device access
22+
- **Container routing** — route any container's traffic through the VPN with a single method call
23+
- **VPN provider support** — typed configuration for OpenVPN and WireGuard, with support for any Gluetun environment variable
24+
- **Aspire parameter integration** — use `ParameterResource` for secrets (private keys, passwords)
25+
- **Docker Compose publish** — routed containers automatically get `network_mode: "service:<vpn>"` and their ports are transferred to the Gluetun service
26+
27+
## Quick Start
28+
29+
<Steps>
30+
1. Install the package into your AppHost project
31+
32+
<NugetBadge name="Shiny.Aspire.Hosting.Gluetun" showLabel={true} />
33+
34+
2. Add a Gluetun VPN container and route other containers through it
35+
36+
```csharp
37+
var builder = DistributedApplication.CreateBuilder(args);
38+
39+
var vpn = builder.AddGluetun("vpn")
40+
.WithVpnProvider("mullvad")
41+
.WithWireGuard(builder.AddParameter("wireguard-key", secret: true))
42+
.WithServerCountries("US", "Canada");
43+
44+
var scraper = builder.AddContainer("scraper", "my-scraper")
45+
.WithHttpEndpoint(targetPort: 8080);
46+
47+
vpn.WithRoutedContainer(scraper);
48+
49+
builder.Build().Run();
50+
```
51+
</Steps>
52+
53+
## AI Coding Assistant
54+
55+
An AI skill is available for Shiny Aspire Gluetun to help configure AppHost and VPN routing directly in your IDE.
56+
57+
**Claude Code**
58+
```bash
59+
claude plugin add github:shinyorg/skills
60+
```
61+
62+
**GitHub Copilot** — Copy the [shiny-aspire](https://github.com/shinyorg/skills/blob/main/skills/shiny-aspire/SKILL.md) skill file into your repository's [custom instructions](https://docs.github.com/en/copilot/customizing-copilot/adding-repository-custom-instructions).
63+
64+
## Requirements
65+
66+
- .NET 10
67+
- .NET Aspire 13.1+
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
---
2+
title: Container Routing
3+
description: Route container traffic through the Gluetun VPN tunnel
4+
---
5+
import NugetBadge from '/src/components/NugetBadge.tsx';
6+
7+
<NugetBadge name="Shiny.Aspire.Hosting.Gluetun" showLabel={true} />
8+
9+
## Routing Containers Through the VPN
10+
11+
Use `WithRoutedContainer` to send a container's traffic through the Gluetun VPN tunnel:
12+
13+
```csharp
14+
var vpn = builder.AddGluetun("vpn")
15+
.WithVpnProvider("mullvad")
16+
.WithWireGuard(builder.AddParameter("wireguard-key", secret: true));
17+
18+
var scraper = builder.AddContainer("scraper", "my-scraper")
19+
.WithHttpEndpoint(targetPort: 8080);
20+
21+
var downloader = builder.AddContainer("downloader", "my-downloader")
22+
.WithHttpEndpoint(targetPort: 9090);
23+
24+
vpn.WithRoutedContainer(scraper);
25+
vpn.WithRoutedContainer(downloader);
26+
```
27+
28+
You can route multiple containers through the same VPN.
29+
30+
## What Happens
31+
32+
Each `WithRoutedContainer` call:
33+
34+
1. Adds a `GluetunRoutedResourceAnnotation` to the Gluetun resource
35+
2. Sets `--network container:<vpn-name>` runtime args on the routed container, so at runtime the container shares the Gluetun network namespace
36+
3. On Docker Compose publish, sets `network_mode: "service:<vpn-name>"` on the routed container and transfers its port mappings to the Gluetun service
37+
38+
## Docker Compose Output
39+
40+
When you publish as Docker Compose, the generated output handles networking and port forwarding automatically:
41+
42+
```yaml
43+
services:
44+
vpn:
45+
image: qmcgaw/gluetun:latest
46+
cap_add:
47+
- NET_ADMIN
48+
devices:
49+
- /dev/net/tun
50+
environment:
51+
- VPN_SERVICE_PROVIDER=mullvad
52+
- VPN_TYPE=wireguard
53+
- WIREGUARD_PRIVATE_KEY=${wireguard-key}
54+
ports:
55+
- "8080:8080" # forwarded from scraper
56+
- "9090:9090" # forwarded from downloader
57+
scraper:
58+
image: my-scraper
59+
network_mode: "service:vpn"
60+
# ports moved to vpn service
61+
downloader:
62+
image: my-downloader
63+
network_mode: "service:vpn"
64+
# ports moved to vpn service
65+
```
66+
67+
Containers using `network_mode: "service:vpn"` share the Gluetun network stack. Since they no longer have their own network namespace, their ports must be exposed on the Gluetun container instead — this transfer is handled automatically.

src/content/docs/aspire/orleans/index.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ An AI skill is available for Shiny Aspire Orleans to help configure AppHost, Sil
109109
claude plugin add github:shinyorg/skills
110110
```
111111

112-
**GitHub Copilot** — Copy the [shiny-aspire-orleans](https://github.com/shinyorg/skills/blob/main/skills/shiny-aspire-orleans/SKILL.md) skill file into your repository's [custom instructions](https://docs.github.com/en/copilot/customizing-copilot/adding-repository-custom-instructions).
112+
**GitHub Copilot** — Copy the [shiny-aspire](https://github.com/shinyorg/skills/blob/main/skills/shiny-aspire/SKILL.md) skill file into your repository's [custom instructions](https://docs.github.com/en/copilot/customizing-copilot/adding-repository-custom-instructions).
113113

114114
## Requirements
115115

src/content/docs/aspire/release-notes.mdx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,17 @@ tableOfContents: true
55

66
import RN from '/src/components/ReleaseNote.astro';
77

8-
## Orleans
8+
## 1.0.0 - TBD
99

10-
### 1.0.0 - February 25, 2026
10+
### Gluetun VPN
11+
<RN type="feature" repo="aspire">Gluetun VPN container as a first-class Aspire resource via `AddGluetun`</RN>
12+
<RN type="feature" repo="aspire">Route container traffic through the VPN via `WithRoutedContainer`</RN>
13+
<RN type="feature" repo="aspire">Typed configuration for OpenVPN and WireGuard with `ParameterResource` support for secrets</RN>
14+
<RN type="feature" repo="aspire">VPN provider, server country/city, proxy, and firewall configuration</RN>
15+
<RN type="feature" repo="aspire">Docker Compose publish support with automatic `network_mode` and port transfer</RN>
16+
<RN type="feature" repo="aspire">Generic environment variable passthrough via `WithGluetunEnvironment`</RN>
17+
18+
### Orleans
1119
<RN type="feature" repo="aspire">Automatic Orleans database schema provisioning from Aspire AppHost via `WithDatabaseSetup`</RN>
1220
<RN type="feature" repo="aspire">Orleans silo ADO.NET configuration via `UseOrleansWithAdoNet`</RN>
1321
<RN type="feature" repo="aspire">Orleans client ADO.NET clustering via `UseOrleansClientWithAdoNet`</RN>

src/content/docs/index.mdx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,9 @@ import allanImg from '/src/assets/allanritchie.jpg';
9999

100100
**Orleans** — Simplified Orleans hosting for Aspire with streamlined AppHost configuration, Silo setup, and client wiring. Get a fully orchestrated Orleans cluster running in your Aspire app with minimal code.
101101

102-
[Get Started](/aspire/orleans/)
102+
**Gluetun VPN** — Model a [Gluetun](https://github.com/qdm12/gluetun) VPN container as a first-class Aspire resource. Route other containers through the VPN tunnel with a single method call, with full Docker Compose publish support.
103+
104+
[Orleans](/aspire/orleans/) · [Gluetun VPN](/aspire/gluetun/)
103105
</Card>
104106
</CardGrid>
105107

@@ -129,7 +131,7 @@ claude plugin add github:shinyorg/skills
129131
| [shiny-reflector](https://github.com/shinyorg/skills/blob/main/skills/shiny-reflector/SKILL.md) | [Reflector](/extensions/reflector) | Source-generated reflection, assembly info, JSON serialization |
130132
| [shiny-extensions](https://github.com/shinyorg/skills/blob/main/skills/shiny-extensions/SKILL.md) | [DI](/extensions/di) · [Stores](/extensions/stores) | Attribute-driven DI registration, key/value stores |
131133
| [localizegen](https://github.com/shinyorg/skills/blob/main/skills/localizegen/SKILL.md) | [Localization Generator](/extensions/localizegen) | Strongly-typed localization from .resx files |
132-
| [shiny-aspire-orleans](https://github.com/shinyorg/skills/blob/main/skills/shiny-aspire-orleans/SKILL.md) | [Aspire Orleans](/aspire/orleans/) | AppHost, Silo, and Client configuration |
134+
| [shiny-aspire](https://github.com/shinyorg/skills/blob/main/skills/shiny-aspire/SKILL.md) | [Aspire Orleans](/aspire/orleans/) | AppHost, Silo, and Client configuration |
133135

134136
---
135137

0 commit comments

Comments
 (0)