Skip to content

Part 3: Add Wi-Fi

The lab network has no Wi-Fi yet. In this part you’ll move the lab into its own file, and broadcast a Lab SSID on it.

Create src/lab.ts with the lab network:

src/lab.ts
import * as UnifiNetwork from "@alchemy-unifi/network";
import * as Effect from "effect/Effect";
export const Lab = Effect.gen(function* () {
const network = yield* UnifiNetwork.Network("lab", {
management: "GATEWAY",
name: "Lab",
vlanId: 50,
enabled: true,
cellularBackupEnabled: false,
internetAccessEnabled: true,
isolationEnabled: false,
zone: UnifiNetwork.FirewallZone.INTERNAL,
ipv4Configuration: {
autoScaleEnabled: false,
hostIpAddress: "192.168.50.1",
prefixLength: 24,
dhcpConfiguration: {
mode: "SERVER",
ipAddressRange: { start: "192.168.50.100", stop: "192.168.50.250" },
leaseTimeSeconds: 86400,
pingConflictDetectionEnabled: true,
},
},
});
return { network };
});

Use Lab in the Stack instead of declaring the network there:

alchemy.run.ts
import * as UnifiNetwork from "@alchemy-unifi/network";
import * as Alchemy from "alchemy";
import * as RemovalPolicy from "alchemy/RemovalPolicy";
import * as Effect from "effect/Effect";
import { Lab } from "./src/lab.ts";
export default Alchemy.Stack(
"UnifiLab",
{ providers: UnifiNetwork.providers(), state: UnifiNetwork.state() },
Effect.gen(function* () {
const lab = yield* UnifiNetwork.Network("lab", {
management: "GATEWAY",
name: "Lab",
vlanId: 50,
enabled: true,
cellularBackupEnabled: false,
internetAccessEnabled: true,
isolationEnabled: false,
zone: UnifiNetwork.FirewallZone.INTERNAL,
ipv4Configuration: {
autoScaleEnabled: false,
hostIpAddress: "192.168.50.1",
prefixLength: 24,
dhcpConfiguration: {
mode: "SERVER",
ipAddressRange: { start: "192.168.50.100", stop: "192.168.50.250" },
leaseTimeSeconds: 86400,
pingConflictDetectionEnabled: true,
},
},
});
const lab = yield* Lab;
yield* UnifiNetwork.Network("default", {
management: "GATEWAY",
name: "Default",
vlanId: 1,
enabled: true,
cellularBackupEnabled: true,
internetAccessEnabled: true,
isolationEnabled: false,
zone: UnifiNetwork.FirewallZone.INTERNAL,
ipv4Configuration: {
autoScaleEnabled: true,
hostIpAddress: "192.168.1.1",
prefixLength: 24,
dhcpConfiguration: {
mode: "SERVER",
ipAddressRange: { start: "192.168.1.6", stop: "192.168.1.254" },
leaseTimeSeconds: 86400,
domainName: "localdomain",
pingConflictDetectionEnabled: true,
},
},
}).pipe(RemovalPolicy.retain());
return { labNetworkId: lab.networkId };
return { labNetworkId: lab.network.networkId };
}),
);

The network keeps its logical ID, lab, so Alchemy sees the same resource and changes nothing.

Broadcast Lab on the lab network:

src/lab.ts
import * as UnifiNetwork from "@alchemy-unifi/network";
import * as Config from "effect/Config";
import * as Effect from "effect/Effect";
export const Lab = Effect.gen(function* () {
const network = yield* UnifiNetwork.Network("lab", {
management: "GATEWAY",
name: "Lab",
vlanId: 50,
enabled: true,
cellularBackupEnabled: false,
internetAccessEnabled: true,
isolationEnabled: false,
zone: UnifiNetwork.FirewallZone.INTERNAL,
ipv4Configuration: {
autoScaleEnabled: false,
hostIpAddress: "192.168.50.1",
prefixLength: 24,
dhcpConfiguration: {
mode: "SERVER",
ipAddressRange: { start: "192.168.50.100", stop: "192.168.50.250" },
leaseTimeSeconds: 86400,
pingConflictDetectionEnabled: true,
},
},
});
yield* UnifiNetwork.WifiBroadcast("lab-wifi", {
type: "STANDARD",
name: "Lab",
enabled: true,
network,
securityConfiguration: {
type: "WPA2_PERSONAL",
passphrase: yield* Config.Redacted("LAB_WIFI_PASSPHRASE"),
fastRoamingEnabled: false,
},
broadcastingFrequenciesGHz: [2.4, 5],
hideName: false,
clientIsolationEnabled: false,
multicastToUnicastConversionEnabled: false,
uapsdEnabled: false,
channel2gLockedTo6: false,
dtimPeriod2gLockedTo3: false,
advertiseDeviceName: false,
arpProxyEnabled: false,
bssTransitionEnabled: true,
});
return { network };
});

network is the lab network, so devices that join the SSID get a lab address.

Config.Redacted reads LAB_WIFI_PASSPHRASE from the environment, and keeps it out of logs and plans. Put it in a .env file next to alchemy.run.ts:

Terminal window
echo 'LAB_WIFI_PASSPHRASE=choose-a-passphrase' >> .env
Terminal window
npx alchemy deploy --stage home

Join Lab from your phone with the passphrase. In the Network app, the phone shows up on the Lab network, with an address from 192.168.50.100 up.

You split the Stack into modules and added Wi-Fi. Next, in Part 4, you’ll wall the lab off with the firewall.