Personal file share — Samba + FileBrowser on EC2
Find a file
dependabot[bot] ba569dffa9
Some checks failed
Deploy / deploy (push) Has been cancelled
bump the minor-and-patch group with 3 updates (#25)
Bumps the minor-and-patch group with 3 updates: [constructs](https://github.com/aws/constructs), [aws-cdk](https://github.com/aws/aws-cdk-cli/tree/HEAD/packages/aws-cdk) and [tsx](https://github.com/privatenumber/tsx).


Updates `constructs` from 10.6.0 to 10.7.0
- [Release notes](https://github.com/aws/constructs/releases)
- [Commits](https://github.com/aws/constructs/compare/v10.6.0...v10.7.0)

Updates `aws-cdk` from 2.1129.0 to 2.1132.0
- [Release notes](https://github.com/aws/aws-cdk-cli/releases)
- [Commits](https://github.com/aws/aws-cdk-cli/commits/aws-cdk@v2.1132.0/packages/aws-cdk)

Updates `tsx` from 4.23.0 to 4.23.1
- [Release notes](https://github.com/privatenumber/tsx/releases)
- [Changelog](https://github.com/privatenumber/tsx/blob/master/release.config.cjs)
- [Commits](https://github.com/privatenumber/tsx/compare/v4.23.0...v4.23.1)

---
updated-dependencies:
- dependency-name: constructs
  dependency-version: 10.7.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: minor-and-patch
- dependency-name: aws-cdk
  dependency-version: 2.1132.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: minor-and-patch
- dependency-name: tsx
  dependency-version: 4.23.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: minor-and-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-17 12:09:31 -04:00
.github chore(ci): SHA-pin org reusable-workflow caller refs (INFRA-50) (#21) 2026-07-06 18:27:22 -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
.gitignore Add .env to gitignore 2026-05-14 17:48:10 -04: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 bump the minor-and-patch group with 3 updates (#25) 2026-07-17 12:09:31 -04:00
package.json bump the minor-and-patch group with 3 updates (#25) 2026-07-17 12:09:31 -04:00
README.md Document CDK app and cdk.json in README (#24) 2026-07-10 16:07:08 -04:00
tsconfig.json Initial file-share stack 2026-05-14 15:23:38 -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