Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions template/shlink/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
## shlink - Self-Hosted URL Shortener

shlink is a powerful, self-hosted URL shortener built with PHP and designed to provide a modern, efficient solution for managing shortened URLs. It offers a robust set of features, including RESTful API support, multiple database compatibility, and extensive customization options. Whether you're running a small personal project or managing large-scale enterprise applications, shlink provides the tools necessary to create, track, and manage short URLs with ease.

### Key Features

- **Self-Hosted Solution**: Fully hostable on your own infrastructure, ensuring complete control over your data and privacy.
- **RESTful API**: A comprehensive and well-documented API for seamless integration with external applications and services.
- **Multiple Database Support**: Compatible with various database systems, including MySQL, PostgreSQL, and SQLite, offering flexibility in deployment.
- **Customizable Short URLs**: Generate short URLs with custom slugs, allowing for branded and memorable links.
- **Detailed Analytics**: Track and analyze click statistics, including geolocation, referrers, and user agents, to gain insights into link performance.
- **QR Code Generation**: Automatically generate QR codes for any shortened URL, enhancing accessibility and usability.
- **Authentication and Security**: Secure access to the application with API key authentication and role-based access control.
- **CLI Tools**: Provides command-line utilities for managing URLs, tags, and other resources directly from the terminal.
- **Extensible via Plugins**: Supports additional functionality through plugins, enabling further customization to meet specific needs.
- **Docker Support**: Simplifies deployment with official Docker images, ensuring consistent environments across development and production.
- **Open Source**: Released under an open-source license, encouraging community contributions and fostering transparency.

shlink is an ideal choice for developers and organizations seeking a reliable, feature-rich URL shortening solution that can be fully tailored to their requirements.

### Notice

1. Protect the login address: Set access restrictions to prevent unauthorized direct access.

2. Use a complex password: Create a password that includes uppercase letters, lowercase letters, numbers, and special characters to increase cracking difficulty.

3. Avoid common usernames: Refrain from using common usernames like "admin" or "root" to reduce the risk of brute-force attacks.

4. Regularly change passwords: It is recommended to update your password periodically to mitigate security risks associated with long-term usage of the same password.

5. Enable multi-factor authentication: Adopt two-factor authentication to add an extra layer of security beyond just the password.

6. Limit login attempts: Set a maximum number of failed login attempts, and temporarily lock the account once it is exceeded to prevent brute-force attacks.

7. Configure unusual login notifications: Set up alerts for abnormal login activity to be informed and respond promptly to potential security issues.

8. Conduct regular security audits: Periodically review account security logs and system configurations to quickly identify and fix potential vulnerabilities.

253 changes: 253 additions & 0 deletions template/shlink/index.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,253 @@
apiVersion: app.sealos.io/v1
kind: Template
metadata:
name: shlink
spec:
title: 'Shlink'
author: 'Sealos'
date: 2025-05-14
url: 'https://shlink.io/'
gitRepo: 'https://github.com/shlinkio/shlink'
description: 'A self-hosted URL shortener with QR code generation, analytics, and REST API.'
readme: 'https://raw.githubusercontent.com/labring-actions/templates/main/template/shlink/README.md'
icon: 'https://shlink.io/images/shlink-logo-blue.svg'
templateType: inline
locale: en
categories:
- web
defaults:
app_name:
type: string
value: shlink-${{ random(8) }}
app_host:
type: string
value: ${{ random(8) }}
inputs:
initial_api_key:
description: 'Initial API key'
type: string
default: ${{ random(8) }}
required: false
mail_from:
description: 'Default "from" address for email notifications'
type: string
default: ''
required: false
geolite_license_key:
description: 'GeoLite license key'
type: string
default: ''
required: false
---

apiVersion: v1
kind: ServiceAccount
metadata:
labels:
sealos-db-provider-cr: ${{ defaults.app_name }}-pg
app.kubernetes.io/instance: ${{ defaults.app_name }}-pg
app.kubernetes.io/managed-by: kbcli
name: ${{ defaults.app_name }}-pg

---

apiVersion: apps/v1
kind: Deployment
metadata:
name: ${{ defaults.app_name }}
annotations:
originImageName: ghcr.io/shlinkio/shlink:latest
deploy.cloud.sealos.io/minReplicas: '1'
deploy.cloud.sealos.io/maxReplicas: '1'
labels:
cloud.sealos.io/app-deploy-manager: ${{ defaults.app_name }}
app: ${{ defaults.app_name }}
spec:
replicas: 1
revisionHistoryLimit: 2
selector:
matchLabels:
app: ${{ defaults.app_name }}
template:
metadata:
labels:
app: ${{ defaults.app_name }}
spec:
automountServiceAccountToken: false
containers:
- name: ${{ defaults.app_name }}
image: ghcr.io/shlinkio/shlink:latest
env:
- name: INITIAL_API_KEY
value: ${{ inputs.initial_api_key }}
- name: PG_PASSWORD
valueFrom:
secretKeyRef:
name: ${{ defaults.app_name }}-pg-conn-credential
key: password
- name: DB_DRIVER
value: postgres
- name: DB_NAME
value: shlink
- name: DB_USER
value: postgres
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: ${{ defaults.app_name }}-pg-conn-credential
key: password
- name: DB_HOST
value: ${{ defaults.app_name }}-pg-postgresql.${{ SEALOS_NAMESPACE }}.svc
- name: DB_PORT
value: "5432"
- name: DEFAULT_DOMAIN
value: ${{ defaults.app_host }}.${{ SEALOS_CLOUD_DOMAIN }}
- name: GEOIP_LICENSE_KEY
value: ${{ inputs.geolite_license_key }}
${{ if(inputs.mail_from !== '') }}
- name: FROM_EMAIL
value: ${{ inputs.mail_from }}
${{ endif() }}
ports:
- containerPort: 8080
resources:
requests:
cpu: 100m
memory: 512Mi
limits:
cpu: 500m
memory: 2Gi
imagePullPolicy: IfNotPresent

---

apiVersion: v1
kind: Service
metadata:
name: ${{ defaults.app_name }}
labels:
cloud.sealos.io/app-deploy-manager: ${{ defaults.app_name }}
spec:
ports:
- port: 80
targetPort: 8080
selector:
app: ${{ defaults.app_name }}

---

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ${{ defaults.app_name }}
labels:
cloud.sealos.io/app-deploy-manager: ${{ defaults.app_name }}
cloud.sealos.io/app-deploy-manager-domain: ${{ defaults.app_host }}
annotations:
kubernetes.io/ingress.class: nginx
spec:
rules:
- host: ${{ defaults.app_host }}.${{ SEALOS_CLOUD_DOMAIN }}
http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: ${{ defaults.app_name }}
port:
number: 80
tls:
- hosts:
- ${{ defaults.app_host }}.${{ SEALOS_CLOUD_DOMAIN }}
secretName: ${{ SEALOS_CERT_SECRET_NAME }}

---

apiVersion: apps.kubeblocks.io/v1alpha1
kind: Cluster
metadata:
finalizers:
- cluster.kubeblocks.io/finalizer
labels:
clusterdefinition.kubeblocks.io/name: postgresql
clusterversion.kubeblocks.io/name: postgresql-14.8.0
sealos-db-provider-cr: ${{ defaults.app_name }}-pg
annotations: {}
name: ${{ defaults.app_name }}-pg
spec:
affinity:
nodeLabels: {}
podAntiAffinity: Preferred
tenancy: SharedNode
topologyKeys: []
clusterDefinitionRef: postgresql
clusterVersionRef: postgresql-14.8.0
backup:
enabled: true
cronExpression: 0 18 * * *
method: backupTool
pitrEnabled: false
retentionPeriod: 7d
componentSpecs:
- componentDefRef: postgresql
monitor: true
name: postgresql
replicas: 1
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 50m
memory: 128Mi
serviceAccountName: ${{ defaults.app_name }}-pg
switchPolicy:
type: Noop
volumeClaimTemplates:
- name: data
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi

terminationPolicy: Delete
tolerations: []

---

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
labels:
sealos-db-provider-cr: ${{ defaults.app_name }}-pg
app.kubernetes.io/instance: ${{ defaults.app_name }}-pg
app.kubernetes.io/managed-by: kbcli
name: ${{ defaults.app_name }}-pg
rules:
- apiGroups:
- '*'
resources:
- '*'
verbs:
- '*'

---

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
labels:
sealos-db-provider-cr: ${{ defaults.app_name }}-pg
app.kubernetes.io/instance: ${{ defaults.app_name }}-pg
app.kubernetes.io/managed-by: kbcli
name: ${{ defaults.app_name }}-pg
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: ${{ defaults.app_name }}-pg
subjects:
- kind: ServiceAccount
name: ${{ defaults.app_name }}-pg