OpenLinks
A self-hosted link-profile platform with identity, analytics, moderation, and object storage.
Purpose and status
OpenLinks is a self-hosted profile and link-publishing application. A creator can maintain a public profile, social identities, ordered links, themes, and basic analytics while keeping application data on personally controlled infrastructure.
Capabilities
Profile publishing
- Reserved and constrained usernames protect system routes and namespace integrity.
- Profiles include display identity, biography, theme configuration, social links, and ordered/pinned links.
- Drag-and-drop packages support deliberate link ordering and profile management.
Platform controls
- Invite-only operation can limit account creation.
- Moderation actions are represented in the database rather than hidden in logs.
- Event and daily analytics separate raw activity from summarized reporting.
Architecture and request flow
The production stack runs three long-lived services: the Next.js app, PostgreSQL 17, and MinIO. A separate initialization profile creates storage resources only when deliberately requested.
Data model and migrations
The recorded Prisma schema includes User, Account, Session, VerificationToken, Profile, SocialLink, Link, AnalyticsEvent, AnalyticsDaily, ReservedUsername, and ModerationAction models. Four production migrations document the initial schema, username constraints, removal of unused theme enums, and moderation support.
Identity and public URL constraints belong in versioned database migrations, not only in interface validation.
Identity, secrets, and storage security
- Auth.js uses the Prisma adapter, with optional GitHub and Google providers.
- Password hashing uses bcrypt for credentials managed by the application.
- Production seeding intentionally skips demo accounts and sample content.
- The application trusts the reverse-proxy host only through deliberate production configuration.
- Database, authentication, OAuth, analytics-salt, and S3 credentials are runtime configuration and are not documented in the wiki.
- Presigned object URLs must use a browser-reachable hostname while storage credentials remain internal.
Operations, backup, and recovery
The application is published on a dedicated host port behind NPM. PostgreSQL is not published to the host. Named volumes preserve database and MinIO data, and the deployment directory contains timestamped database backups plus a restoration script.
Preflight
- Generate Prisma client, type-check, build, and validate Compose.
- Confirm database health before application startup.
- Verify public URL and S3 signing configuration agree.
- Draft the OpenLinks wiki changes for the planned version, schema, identity, storage, and operating-model update.
Postflight
- Test sign-in, profile rendering, link ordering, uploads, and access denial.
- Confirm app, PostgreSQL, and MinIO health.
- Restore a backup into an isolated test before calling recovery complete.
- Update the OpenLinks wiki with the verified release, migrations, limitations, recovery evidence, and lessons.
Lessons and roadmap
- Public usernames are security-sensitive routing data and need reserved-name protection.
- Authentication behind a reverse proxy requires trusted-host configuration and accurate public origins.
- Object storage introduces two endpoints: the private service endpoint and the safe public signing origin.
- Analytics should minimize retained personal data and use protected salts.
- Future work should add documented release tags, automated tests, upload lifecycle checks, and scheduled restoration drills.