Skip to content

Commit

Permalink
New tutorial - "Setup custom domain with S3-compatible object storage"
Browse files Browse the repository at this point in the history
  • Loading branch information
ivan-zaitsev committed Jan 4, 2025
1 parent 1cd6ac6 commit 8c54502
Showing 1 changed file with 233 additions and 0 deletions.
233 changes: 233 additions & 0 deletions tutorials/hetzner-object-storage-custom-domain/01.en.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
---
SPDX-License-Identifier: MIT
path: "/tutorials/hetzner-object-storage-custom-domain"
slug: "hetzner-object-storage-custom-domain"
date: "2025-01-05"
title: "Setup custom domain with S3-compatible object storage"
short_description: "This tutorial explains how to setup custom domain for S3-compatible object storage using reverse proxy."
tags: ["Custom domain", "Reverse proxy", "Object Storage"]
author: "Ivan Zaitsev"
author_link: "https://github.com/ivan-zaitsev"
author_img: "https://avatars.githubusercontent.com/u/15122759"
author_description: ""
language: "en"
available_languages: ["en"]
header_img: "header-7"
cta: "cloud"
---

## Introduction

This tutorial will guide you to setup custom domain for S3-compatible object storage using reverse proxy.
The advantages of custom domain is to enable seamless integration with existing infrastructure or services under a unified domain.

A custom domain can be configured in various ways, such as using a CNAME record or a reverse proxy.
This tutorial focuses on configuring a custom domain using a reverse proxy.

**Prerequisites**

* A server (e.g. with [Hetzner Cloud](https://www.hetzner.com/cloud/))
* A S3-compatible bucket (e.g. with [Hetzner](https://www.hetzner.com))
* A domain you want to use (e.g. `storage.example.com`).

## Step 1 - Create Object Storage Bucket

Create a S3-compatible bucket.
With Hetzner, see the getting started "[Creating a Bucket](https://docs.hetzner.com/storage/object-storage/getting-started/creating-a-bucket)".
Make sure it is set to public access permissions. No much benefit of using custom domain for private buckets.

Create S3 credentials to access your bucket.
With Hetzner, see the getting started "[Generating S3 keys](https://docs.hetzner.com/storage/object-storage/getting-started/generating-s3-keys)".

## Step 2 - Create Server

Create a new server.
With Hetzner, see the getting started "[Creating a Server](https://docs.hetzner.com/cloud/servers/getting-started/creating-a-server)").
To install Docker and Docker Compose, follow the [official Docker documentation](https://docs.docker.com/engine/install/).

## Step 3 - Deploy Caddy

SSH to your server `ssh root@<server-ip>`.

Create a directory for your Docker Compose files and folders for the persistent storage of the Caddy container:

```bash
mkdir -p /opt/caddy/data
```

### Step 3.1 - Create docker deployment and configuration files

`vim /opt/caddy/compose.yaml`

```yaml
services:
caddy:
container_name: caddy
image: caddy:latest
restart: unless-stopped
ports:
- 80:80
- 443:443
volumes:
- ./data/Caddyfile:/etc/caddy/Caddyfile
- ./data/certs:/certs
- ./data/config:/config
- ./data/data:/data
- ./data/sites:/srv
```
`vim /opt/caddy/data/Caddyfile`

```text
storage.example.com {
tls {
issuer acme {
dir https://acme-v02.api.letsencrypt.org/directory
}
}
}
storage.example.com:443 {
reverse_proxy https://fsn1.your-objectstorage.com {
header_up Host {http.reverse_proxy.upstream.hostport}
header_up X-Forwarded-Host {host}
}
}
```

### Step 3.2 - Start Caddy

```bash
cd /opt/caddy
docker compose up -d
```

**Note:**

The request url would be `https://storage.example.com/bucket-name/object.txt`. I
It is equivalent to `https://fsn1.your-objectstorage.com/bucket-name/object.txt`.

### Step 3.3 - Create kubernetes deployment and configuration files (Optional)

Assuming you already have configured kubernetes, gateway api.

```yaml
apiVersion: v1
kind: Service
metadata:
name: caddy-storage
namespace: caddy
spec:
type: ClusterIP
selector:
service: caddy-storage
ports:
- name: http
protocol: TCP
port: 80
targetPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: caddy-storage
namespace: caddy
spec:
replicas: 1
revisionHistoryLimit: 3
selector:
matchLabels:
service: caddy-storage
template:
metadata:
labels:
service: caddy-storage
spec:
containers:
- image: "caddy:latest"
name: caddy
ports:
- name: http
protocol: TCP
containerPort: 80
volumeMounts:
- name: config-volume
mountPath: /etc/caddy
volumes:
- name: config-volume
configMap:
name: caddy-storage-config
---
apiVersion: v1
kind: ConfigMap
metadata:
name: caddy-storage-config
namespace: caddy
data:
Caddyfile: |
storage.example.com:80 {
reverse_proxy https://fsn1.your-objectstorage.com {
header_up Host {http.reverse_proxy.upstream.hostport}
header_up X-Forwarded-Host {host}
}
}
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: caddy-storage-route
namespace: caddy
spec:
parentRefs:
- name: kubernetes-gateway
namespace: istio-gateway
hostnames:
- "storage.example.com"
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: caddy-storage
port: 80
weight: 100
```

##### License: MIT

<!--

Contributor's Certificate of Origin

By making a contribution to this project, I certify that:

(a) The contribution was created in whole or in part by me and I have
the right to submit it under the license indicated in the file; or

(b) The contribution is based upon previous work that, to the best of my
knowledge, is covered under an appropriate license and I have the
right under that license to submit that work with modifications,
whether created in whole or in part by me, under the same license
(unless I am permitted to submit under a different license), as
indicated in the file; or

(c) The contribution was provided directly to me by some other person
who certified (a), (b) or (c) and I have not modified it.

(d) I understand and agree that this project and the contribution are
public and that a record of the contribution (including all personal
information I submit with it, including my sign-off) is maintained
indefinitely and may be redistributed consistent with this project
or the license(s) involved.

Signed-off-by: Ivan Zaitsev, https://github.com/ivan-zaitsev

-->

0 comments on commit 8c54502

Please sign in to comment.