Personal file share — Samba + FileBrowser on EC2
Find a file
2026-08-24 14:26:26 -04:00
.github chore(ci): remove pr policy workflow caller 2026-08-24 14:26:26 -04:00
.security-review Merge pull request #34 from Sea-Haven-Industries/dependabot/npm_and_yarn/minor-and-patch-de6c8d5989 2026-08-07 13:18:04 -04:00
bin Initial file-share stack 2026-05-14 15:23:38 -04:00
lib fix(infra): adopt existing data volume + cache AMI to stop replacement churn (#5) 2026-06-05 13:40:05 -04:00
test fix(ci): enable Jest CDK stack tests 2026-08-07 12:19:12 -04:00
.gitignore Add .env to gitignore 2026-05-14 17:48:10 -04:00
.mergify.yml chore(ci): switch auto-merge from seahaven-bot to Mergify (#43) 2026-08-24 13:52:47 -04:00
AGENTS.md Add AGENTS.md with CDK + EC2 + persistent-EBS conventions (#26) 2026-07-28 19:54:49 +00:00
cdk.context.json fix(infra): adopt existing data volume + cache AMI to stop replacement churn (#5) 2026-06-05 13:40:05 -04:00
cdk.json build(deps): migrate CDK app ts-node->tsx, adopt typescript 7 (INFRA-183) (#22) 2026-07-08 17:48:26 -04:00
package-lock.json build(deps): bump the minor-and-patch group with 3 updates (#38) 2026-08-21 11:12:20 -04:00
package.json build(deps): bump the minor-and-patch group with 3 updates (#38) 2026-08-21 11:12:20 -04:00
README.md Document CDK app and cdk.json in README (#24) 2026-07-10 16:07:08 -04:00
tsconfig.json fix(ci): enable Jest CDK stack tests 2026-08-07 12:19:12 -04:00

file-share

CI TypeScript AWS CDK

Personal file share server on AWS — Samba for macOS Finder integration and FileBrowser for web-based file management. Accessible exclusively over the site-to-site VPN.

Infrastructure (CDK)

All infrastructure is defined as code with the AWS CDK (TypeScript). The app synthesizes a single CloudFormation stack — file-share — that provisions everything described under Architecture, deployed to account 328440206208 in us-east-1.

bin/app.ts                 # CDK app entry point — instantiates the stack
lib/file-share-stack.ts    # FileShareStack — all resource definitions
cdk.json                   # App command + CDK feature flags / context
cdk.context.json           # Cached VPC/subnet lookups and the resolved AL2023 AMI

cdk.json is the CDK app manifest. Its app command (npx tsx bin/app.ts) runs the TypeScript entry point directly via tsx — no separate compile step is needed for synth or deploy. bin/app.ts instantiates FileShareStack with an explicit stackName: "file-share" (kebab-case, per convention) and the target account/region.

aws-cdk-lib is pinned to an exact version (2.261.0); the aws-cdk CLI is available as a dev dependency and via npx cdk.

Common commands (also exposed as npm scripts):

Command Purpose
npx cdk synth (npm run synth) Synthesize the CloudFormation template to cdk.out/
npx cdk diff (npm run diff) Diff the synthesized stack against what is deployed
npx cdk deploy (npm run deploy) Deploy the stack
npm run build Type-check via tsc

Architecture

  • EC2 — t4g.small (ARM64, Amazon Linux 2023) in the private subnet. The AMI is cached in the committed cdk.context.json (cachedInContext: true), so deploys never pick up a new AL2023 release implicitly — an AMI change forces instance replacement and must be deliberate (cdk context --reset <ami key> && cdk synth).
  • Samba — SMB file share at /data/share, optimized for macOS (vfs_fruit)
  • FileBrowser — Web UI on port 8080, backed by the same /data/share directory
  • SFTP — password auth for user adam (ForceCommand internal-sftp, same password as SMB); used by Hazel for automated uploads
  • EBS data volume — vol-04d951cccacc435b5, 500 GiB gp3 encrypted, mounted at /data. Unmanaged import: the stack references it by ID (Volume.fromVolumeAttributes + CfnVolumeAttachment), so CloudFormation can attach it but can never create, replace, or delete it — the data survives instance replacement and even stack deletion. UserData waits for the attachment, then mounts the existing filesystem; a blkid guard ensures a disk that already has a filesystem is never formatted.
  • DLM — Daily EBS snapshots at 06:00 UTC, 30-day retention (targets the file-share-backup=true tag, set directly on the volume)
  • SSM — Session Manager for instance access (no SSH key)

History: the data volume was originally an inline blockDevice, which destroyed data on instance replacement (2026-05-27 incident), then a stack-managed standalone volume, which was orphaned when an uncommitted deploy got reverted by CD (2026-06-05 incident). The unmanaged-import design ends that failure class.

Documentation

The canonical map of Sea Haven's AWS infrastructure lives in Confluence. This project's file-share stack is represented there as a Mermaid subgraph.

Access

Requires VPN connection to the office network (10.10.0.0/16).

Finder (SMB)

  1. Finder > Go > Connect to Server
  2. Enter smb://<private-ip>/files
  3. Authenticate with adam and the password from file-share/smb-password in Secrets Manager

FileBrowser (Web)

Open http://<private-ip>:8080 in a browser.

Secrets

Both stored in AWS Secrets Manager:

Secret Purpose
file-share/smb-password Samba user password
file-share/filebrowser-password FileBrowser admin password

Create these secrets before deploying the stack:

aws secretsmanager create-secret --name file-share/smb-password --secret-string '<password>'
aws secretsmanager create-secret --name file-share/filebrowser-password --secret-string '<password>'

Deploy

npm install
npx cdk deploy

The stack outputs the instance's private IP for SMB and FileBrowser access.

Expanding Storage

The data volume is not managed by CloudFormation (imported by ID), so changing a size in lib/file-share-stack.ts has no effect. Expand it directly — no downtime:

  1. aws ec2 modify-volume --volume-id vol-04d951cccacc435b5 --size <new-GiB>
  2. Wait for the modification to leave modifying: aws ec2 describe-volumes-modifications --volume-ids vol-04d951cccacc435b5
  3. Resize the filesystem via an SSM session:
    sudo resize2fs /dev/nvme1n1   # xvdf surfaces as nvme1n1 on Nitro instances