Skip to content

Commit 3a2ec0e

Browse files
committed
Replace the URL shortener chart
1 parent c6efd32 commit 3a2ec0e

15 files changed

Lines changed: 162 additions & 197 deletions

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,5 +55,5 @@ Here's a summary of which additional tools this repository offers:
5555

5656
- [AppifyHub's Monolith API](./appifyhub-api/README.md): The API service from the [AppifyHub Monolith repository](https://github.com/appifyhub/monolith)
5757
- [The Agent's API](./the-agent-api/README.md): The service from [The Agent repository](https://github.com/appifyhub/the-agent)
58-
- [n8n Workflow Automation](./n8n/README.md): The n8n workflow automation platform for connecting apps and automating workflows
59-
- [shrtn URL Shortener](./shrtn/README.md): The shrtn URL shortener for creating short URLs
58+
- [Workflow Automations](./n8n/README.md): The n8n workflow automation platform for connecting apps and automating workflows
59+
- [URL Shortener](./url-shortener/README.md): A generic URL shortener powered by Shlink

shrtn/Chart.yaml

Lines changed: 0 additions & 5 deletions
This file was deleted.

shrtn/templates/config-map.yaml

Lines changed: 0 additions & 17 deletions
This file was deleted.

shrtn/values.yaml

Lines changed: 0 additions & 103 deletions
This file was deleted.

url-shortener/Chart.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
apiVersion: v2
2+
name: url-shortener
3+
description: URL Shortener
4+
version: 1.0.0
5+
type: application
Lines changed: 34 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
# shrtn URL Shortener
1+
# URL Shortener (Shlink)
22

3-
This directory contains the Kubernetes (K8s) configuration and Helm chart manifests for deploying shrtn, a self-hosted URL shortener. Learn more at [shrtn.io](https://shrtn.io) and [GitHub](https://github.com/CordlessWool/shrtn).
3+
This directory contains the Kubernetes (K8s) configuration and Helm chart manifests for deploying a URL shortener powered by Shlink. Learn more at [Shlink](https://shlink.io).
44

55
### How to use this?
66

7-
Most of the prerequisites are available for exploration in the [root-level README](../README.md). This document will focus only on the specific steps needed to deploy shrtn.
7+
Most of the prerequisites are available for exploration in the [root-level README](../README.md). This document will focus only on the specific steps needed to deploy the URL shortener.
88

99
Prerequisites:
1010

@@ -17,30 +17,20 @@ Prerequisites:
1717

1818
## Installation Guide
1919

20-
This URL shortener is best deployed using a Helm chart, which is located next to this guide. The chart is designed to be installed into a K8s cluster, and it will create all of the necessary resources for shrtn to run.
20+
This URL shortener is best deployed using a Helm chart, which is located next to this guide. The chart is designed to be installed into a K8s cluster, and it will create all of the necessary resources for Shlink to run.
2121

22-
This chart uses SQLite as the database backend by default, which is stored in a persistent volume. This is suitable for small to medium workloads. For production environments with high availability requirements, consider using PostgreSQL or Cloudflare D1 instead (see shrtn documentation for details).
22+
This chart uses SQLite as the database backend by default, which is stored in a persistent volume. This is suitable for small to medium workloads. For production environments with high availability requirements, consider using PostgreSQL later (see Shlink documentation for details).
2323

2424
Going forward, we will assume that you want to manage secrets using [Doppler](https://www.doppler.com). If you don't want to use Doppler, you can create the secrets manually using the `kubectl create secret` command and disable Doppler via Helm value directives. More details on how Doppler manages secrets can be found in the [Secrets Check](../secrets-check/README.md) guide.
2525

2626
#### Required Secrets Configuration
2727

28-
Before deploying shrtn, you need to set up the following secrets in your Doppler project (or K8s secrets if not using Doppler):
28+
Before deploying the URL shortener, you need to set up the following secrets in your Doppler project (or K8s secrets if not using Doppler):
2929

30-
##### Core Required Configuration
30+
1. `GEOLITE_LICENSE_KEY` — Maxmind GeoLite2 license key. See [GeoLite2 license key](https://shlink.io/documentation/geolite-license-key/).
31+
2. `INITIAL_API_KEY` — Bootstrap API key for Shlink. See [Install via Docker](https://shlink.io/documentation/install-docker-image/).
3132

32-
1. **`ORIGIN`** - Base URL for the public-facing site
33-
- Example: `http://shrtn.example.com` or `https://shrtn.example.com`
34-
- This is also available as a config value, but can be overridden via secrets
35-
- Required for proper URL generation
36-
37-
2. **`DATABASE_URL`** (Optional) - Database connection string
38-
- Default: SQLite file (`file:sqlite_file_name.db`) - stored in persistent volume
39-
- For PostgreSQL: `postgresql://user:password@host:5432/database`
40-
- For Cloudflare D1: See shrtn documentation for libSQL connection string
41-
- **Note**: If using PostgreSQL, include credentials here or set via secrets
42-
43-
For other configuration options and secrets, see the `values.yaml` file or the shortener's documentation.
33+
For other configuration options and secrets, see the `values.yaml` file or the Shlink documentation.
4434

4535
### The basic setup
4636

@@ -50,22 +40,20 @@ Let's install the chart:
5040
# Prepare a dedicated namespace (if not already there)
5141
kubectl create namespace delete-me
5242
# Install the service from there
53-
helm install shrtn appifyhub/shrtn \
43+
helm install url-shortener appifyhub/url-shortener \
5444
--namespace delete-me \
5545
--set secrets.provider="none"
5646
```
5747

58-
This basic setup **does not** automatically manage your secrets, and expects you to have them provided next to your new deployment. The ORIGIN will default to the value in `values.yaml` (`http://shrtn.cloud.appifyhub.local`).
48+
This basic setup does not automatically manage your secrets. The `DEFAULT_DOMAIN` and `IS_HTTPS_ENABLED` values will be computed from the chart's `ingress.*` configuration by default.
5949

60-
The service created here will be exposed over HTTP (not HTTPS) at `http://shrtn.cloud.appifyhub.local`. Note the `.local` top-level domain: this is a fake domain that is used for development and testing. You can change this to a real domain in the next steps. In order to access the service on this fake domain, you need to add it to your local hosts file (e.g., `/etc/hosts`), as explained in the [Echo server](../echo/README.md) guide. In the next step, we will explore adding the secrets manager and a real domain.
61-
62-
**Important**: Short URL redirects (like `https://shrtn.example.com/abc123`) will always work publicly - only the creation/admin interface will be restricted.
50+
The service here will typically be exposed over HTTP (TLS is terminated at Traefik/edge). In production behind Traefik/Cloudflare, set `IS_HTTPS_ENABLED=true` to ensure Shlink generates correct HTTPS links.
6351

6452
Here's how you can undo this installation if you want to start over:
6553

6654
```bash
67-
# Uninstall shrtn
68-
helm uninstall shrtn --namespace delete-me
55+
# Uninstall the URL shortener
56+
helm uninstall url-shortener --namespace delete-me
6957
# Remove the namespace if you don't need it anymore
7058
kubectl delete namespace delete-me
7159
```
@@ -86,38 +74,36 @@ Because a configuration based on a real domain is not assumed as the default, re
8674
# Prepare a dedicated namespace (if not already there)
8775
kubectl create namespace staging
8876
# Install the service from there - assuming you want it in a 'staging' namespace
89-
helm install shrtn appifyhub/shrtn \
77+
helm install url-shortener appifyhub/url-shortener \
9078
--namespace staging \
9179
--set app.image.tag="latest" \
92-
--set secrets.doppler.project="shrtn-cloud" \
80+
--set secrets.doppler.project="url-shortener-cloud" \
9381
--set secrets.doppler.config="staging" \
9482
--set secrets.doppler.token="dp.st.staging.your-actual-token-here" \
9583
--set ingress.domain.base="realdomain.com" \
96-
--set ingress.domain.prefix="shrtn" \
97-
--set config.values.ORIGIN="http://shrtn.realdomain.com"
84+
--set ingress.domain.prefix="url-shortener"
9885
```
9986

10087
Note that this setup is also implicitly enabling Doppler's secrets manager, which will automatically inject the secrets into your pods. For more information on how to set up Doppler, check the [Secrets Check](../secrets-check/README.md) guide.
10188

10289
> 💡   The deployment is configured to reload its secrets every 5 minutes. In addition, the deployment might create multiple pods while booting up. As soon as the pod with the secrets injected is up and running, the other pod will be shut down (potentially with some logged errors). This is normal behavior.
10390
104-
Make sure your Doppler project contains all the required secrets (at minimum `ORIGIN`) before deploying.
91+
Make sure your Doppler project contains at least `GEOLITE_LICENSE_KEY` and `INITIAL_API_KEY` before deploying.
10592

10693
### TLS and HTTPS
10794

10895
The configurations shown so far are not using TLS or HTTPS. This is fine for development and testing, but in production, we should always use TLS and HTTPS to secure our traffic. We will now make some changes to the chart to enable TLS and HTTPS.
10996

11097
```bash
11198
# Let's upgrade our existing Helm release to include TLS and HTTPS
112-
helm upgrade shrtn appifyhub/shrtn \
99+
helm upgrade url-shortener appifyhub/url-shortener \
113100
--namespace staging \
114101
--set app.image.tag="latest" \
115-
--set secrets.doppler.project="shrtn-cloud" \
102+
--set secrets.doppler.project="url-shortener-cloud" \
116103
--set secrets.doppler.config="staging" \
117104
--set secrets.doppler.token="dp.st.staging.your-actual-token-here" \
118105
--set ingress.domain.base="realdomain.com" \
119-
--set ingress.domain.prefix="shrtn" \
120-
--set config.values.ORIGIN="https://shrtn.realdomain.com" \
106+
--set ingress.domain.prefix="url-shortener" \
121107
--set ingress.tls.enabled=true \
122108
--set-string ingress.annotations."traefik\.ingress\.kubernetes\.io/router\.entrypoints"=websecure \
123109
--set-string ingress.annotations."traefik\.ingress\.kubernetes\.io/router\.tls"=true \
@@ -126,46 +112,40 @@ helm upgrade shrtn appifyhub/shrtn \
126112

127113
> 💡   The deployment here relies on Traefik's integration with [Let's Encrypt](https://letsencrypt.org), a widely-used provider of free TLS certificates. The chart is now configured to use the `websecure` entrypoint, which is the default entrypoint for HTTPS traffic in Traefik. If you are using a different ingress controller, you need to adjust accordingly yourself.
128114
129-
Note that we've also updated the `ORIGIN` configuration value to use HTTPS. This is important for shortened URLs to work correctly.
115+
Also set `IS_HTTPS_ENABLED=true` so Shlink generates HTTPS links.
116+
130117

131118
It may take a few minutes for the TLS certificate to be issued and for the service to be accessible over HTTPS.
132119

133120
#### Additional configuration
134121

135-
In addition to the install values we changed above using `--set`, there are many other configuration options available in the chart (such as rollback history, resource consumption, TTL settings, etc). You can see all of them in the `values.yaml` file.
122+
In addition to the install values we changed above using `--set`, there are many other configuration options available in the chart (such as rollback history, resource consumption, TTL settings, etc).
123+
124+
See `values.yaml` for overridable non-sensitive config and future DB/Redis toggles.
136125

137126
## Important Considerations
138127

139128
### Backups
140129

141-
Since shrtn uses SQLite stored in a persistent volume by default, it's critical to backup your data regularly. You can backup the persistent volume using your cloud provider's snapshot features or by using Kubernetes backup solutions like Velero.
130+
Since Shlink uses SQLite stored in a persistent volume by default, it's critical to backup your data regularly. You can backup the persistent volume using your cloud provider's snapshot features or by using Kubernetes backup solutions like Velero.
142131

143-
To manually backup shrtn data:
132+
To manually backup data:
144133

145134
```bash
146135
# Get the pod name
147-
POD_NAME=$(kubectl get pods -n staging -l app=shrtn -o jsonpath='{.items[0].metadata.name}')
136+
POD_NAME=$(kubectl get pods -n staging -l app=url-shortener -o jsonpath='{.items[0].metadata.name}')
148137

149138
# Copy the data directory from the pod
150-
kubectl cp staging/$POD_NAME:/data ./shrtn-backup
139+
kubectl cp staging/$POD_NAME:/etc/shlink ./url-shortener-backup
151140
```
152141

153142
### Scaling Limitations
154143

155-
This chart uses SQLite as the database backend by default, which means:
144+
This chart uses SQLite by default, which means:
156145

157-
- **Only 1 replica is supported** - SQLite doesn't support multiple concurrent connections from different pods
158-
- For high availability and horizontal scaling, you need to configure shrtn to use PostgreSQL or Cloudflare D1 instead
159-
- See the [shrtn documentation](https://github.com/CordlessWool/shrtn) for database setup options
146+
- Only 1 replica is supported
147+
- For high availability and horizontal scaling, you need to move to Postgres and configure a shared Redis/Valkey for locks
160148

161149
### Persistent Volume
162150

163-
The chart creates a persistent volume of 5Gi by default. This should be sufficient for most small to medium deployments. If you're planning to:
164-
165-
- Store a large number of shortened URLs
166-
- Keep extensive analytics data
167-
- Store user-generated content
168-
169-
You should increase the volume size by setting `--set persistence.size=10Gi` (or larger) during installation, if needed.
170-
171-
> ⚠️   **Note**: You cannot easily resize a persistent volume after creation in most cloud environments. Plan your storage needs accordingly.
151+
The chart creates a persistent volume of 10Gi by default. Increase via `--set persistence.size=20Gi` if needed.
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
Thank you for installing {{ .Chart.Name }}!
22

3-
Your shrtn URL shortener has been deployed.
3+
Your URL shortener (powered by Shlink) has been deployed.
44

5-
To access shrtn:
5+
To access the service:
66

77
1. Get the application URL:
88
{{- if .Values.ingress.enabled }}
@@ -16,14 +16,14 @@ To access shrtn:
1616
Then access: http://localhost:{{ .Values.app.servicePort }}
1717
{{- end }}
1818

19-
2. On first access, you'll be able to start shortening URLs immediately.
19+
2. Authenticate using your INITIAL_API_KEY from your secrets ({{ .Values.secrets.provider }})
2020

2121
Important notes:
2222

23-
- Your shrtn data is stored in a persistent volume at {{ .Values.persistence.mountPath }}
24-
- Database configuration can be set via DATABASE_URL environment variable (defaults to SQLite)
25-
- For production, consider using PostgreSQL by setting DATABASE_URL in your secrets ({{ .Values.secrets.provider }})
26-
- Mail configuration (MAIL_PROVIDER, MAIL_*, etc.) should be set in your secrets for email functionality
23+
- Your data is stored in a persistent volume at {{ .Values.persistence.mountPath }}
24+
- Using SQLite database by default (suitable for small to medium workloads)
25+
- For production and high availability, consider using PostgreSQL with DB_* environment variables
26+
- GeoLite2 license key (GEOLITE_LICENSE_KEY) is required for geolocation features
2727
- Regular backups of the persistent volume are recommended
2828

29-
For more information, visit: https://github.com/CordlessWool/shrtn
29+
For more information, visit: https://shlink.io
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{{- if .Values.config.enabled }}
2+
apiVersion: v1
3+
kind: ConfigMap
4+
5+
metadata:
6+
name: {{ .Release.Name }}-config
7+
labels:
8+
app: {{ .Values.app.name }}
9+
instance: {{ .Release.Name }}
10+
app.kubernetes.io/name: {{ .Values.app.name }}
11+
app.kubernetes.io/instance: {{ .Release.Name }}
12+
13+
data:
14+
# Computed defaults (overridable via config.values)
15+
{{- $cfg := .Values.config.values | default dict }}
16+
DEFAULT_DOMAIN: {{ default (printf "%s.%s" .Values.ingress.domain.prefix .Values.ingress.domain.base) (index $cfg "DEFAULT_DOMAIN") | quote }}
17+
IS_HTTPS_ENABLED: {{ default (ternary "true" "false" .Values.ingress.tls.enabled) (index $cfg "IS_HTTPS_ENABLED") | quote }}
18+
19+
# Additional non-sensitive config values (excluding computed keys if provided above)
20+
{{- if $cfg }}
21+
{{- range $key, $value := $cfg }}
22+
{{- if and (ne $key "DEFAULT_DOMAIN") (ne $key "IS_HTTPS_ENABLED") }}
23+
{{ $key }}: {{ $value | quote }}
24+
{{- end }}
25+
{{- end }}
26+
{{- end }}
27+
{{- end }}

0 commit comments

Comments
 (0)