# 11-linkstack.md

kstack:
  book: Centerpoint Home Lab
  chapter: Documents & Organization
  page: LinkStack
  tags: [linkstack, linktree, about-me, public, website]
---

## Overview

LinkStack is a self-hosted link-in-bio / personal landing page, serving as the
public-facing "about me" page and link hub for `jeevesconsults.ca`. It responds
to two separate domain names on a single Traefik route: the primary
`aboutme.jeevesconsults.ca` and the root `www.jeevesconsults.ca`.

## Access

| URL                                  | Auth          |
|--------------------------------------|---------------|
| `https://aboutme.jeevesconsults.ca`  | Public — no auth |
| `https://www.jeevesconsults.ca`      | Public — no auth |

Both hostnames resolve to the same LinkStack instance. No authentication
middleware — this is a public-facing page.

## Configuration

**Image:** `linkstackorg/linkstack:latest`

### Environment Variables

| Variable               | Value / Notes                        |
|------------------------|--------------------------------------|
| `HTTPS_SERVER_NAME`    | `aboutme.jeevesconsults.ca`          |
| `SERVER_ADMIN`         | `ask@jeevesconsults.ca`              |
| `PHP_MEMORY_LIMIT`     | `512M`                               |
| `UPLOAD_MAX_FILESIZE`  | `8M`                                 |
| `TZ`                   | `America/Toronto`                    |

### Traefik Labels

```yaml
traefik.http.routers.linkstack.rule: Host(`aboutme.jeevesconsults.ca`) || Host(`www.jeevesconsults.ca`)
traefik.http.routers.linkstack.entrypoints: websecure
traefik.http.routers.linkstack.tls.certresolver: letsencrypt
traefik.http.services.linkstack.loadbalancer.server.port: 80
```

> The `||` in the Traefik host rule matches either domain — both resolve to the
> same container and present the same LinkStack profile.

## Volumes / Bind Mounts

| Host Path                            | Container Path | Purpose                  |
|--------------------------------------|----------------|--------------------------|
| `/home/jeeves/docker/linkstack/data` | `/htdocs`      | App files, config, SQLite |

## Notes / Gotchas

- `HTTPS_SERVER_NAME` is set to `aboutme.jeevesconsults.ca`. Even though both
  domains are handled by Traefik, LinkStack internally uses this value for
  canonical URL generation. Links may contain this hostname.
- No GeoBlock or CrowdSec on this route — it is intentionally fully public.
  Monitor access logs if abuse is suspected.
- LinkStack stores its own SQLite database and assets under `/htdocs`. The
  entire `data/` bind mount must be backed up to preserve the profile content.
- Letsencrypt will issue certificates for both `aboutme.jeevesconsults.ca` and
  `www.jeevesconsults.ca` via the same Traefik router — both must resolve to
  Centerpoint's public IP in DNS for certificate issuance to succeed.

---
*Last Updated: 2026-06-17*