mirror of
https://github.com/ditatompel/insights.git
synced 2025-01-08 03:12:06 +07:00
Compare commits
1 commit
d5d3f7d8b7
...
a5ccaffef3
Author | SHA1 | Date | |
---|---|---|---|
|
a5ccaffef3 |
13 changed files with 12 additions and 644 deletions
|
@ -9,12 +9,12 @@ hb:
|
||||||
# see https://hbstack.dev/en/docs/modules/socials/.
|
# see https://hbstack.dev/en/docs/modules/socials/.
|
||||||
socials:
|
socials:
|
||||||
github: https://github.com/ditatompel/insights
|
github: https://github.com/ditatompel/insights
|
||||||
youtube: https://www.youtube.com/channel/UCDV5fWBAvJdULelWdOa3ubQ
|
youtube: https://www.youtube.com/channel/UCDV5fWBAvJdULelWdOa3ubQ?sub_confirmation=1
|
||||||
footer:
|
footer:
|
||||||
# see https://hbstack.dev/en/docs/modules/socials/.
|
# see https://hbstack.dev/en/docs/modules/socials/.
|
||||||
socials:
|
socials:
|
||||||
github: https://github.com/ditatompel/insights
|
github: https://github.com/ditatompel/insights
|
||||||
youtube: https://www.youtube.com/channel/UCDV5fWBAvJdULelWdOa3ubQ
|
youtube: https://www.youtube.com/channel/UCDV5fWBAvJdULelWdOa3ubQ?sub_confirmation=1
|
||||||
blog:
|
blog:
|
||||||
paginate: 12 # paginate.
|
paginate: 12 # paginate.
|
||||||
# post_thumbnail: false # whether to show the thumbnails.
|
# post_thumbnail: false # whether to show the thumbnails.
|
||||||
|
|
|
@ -7,5 +7,5 @@ socials:
|
||||||
github: ditatompel
|
github: ditatompel
|
||||||
website: https://www.ditatompel.com
|
website: https://www.ditatompel.com
|
||||||
patreon: svcadm
|
patreon: svcadm
|
||||||
youtube: https://www.youtube.com/channel/UCDV5fWBAvJdULelWdOa3ubQ
|
youtube: https://www.youtube.com/channel/UCDV5fWBAvJdULelWdOa3ubQ?sub_confirmation=1
|
||||||
---
|
---
|
||||||
|
|
|
@ -7,5 +7,5 @@ socials:
|
||||||
github: ditatompel
|
github: ditatompel
|
||||||
website: https://www.ditatompel.com
|
website: https://www.ditatompel.com
|
||||||
patreon: svcadm
|
patreon: svcadm
|
||||||
youtube: https://www.youtube.com/channel/UCDV5fWBAvJdULelWdOa3ubQ
|
youtube: https://www.youtube.com/channel/UCDV5fWBAvJdULelWdOa3ubQ?sub_confirmation=1
|
||||||
---
|
---
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 68 KiB |
Binary file not shown.
Before Width: | Height: | Size: 23 KiB |
Binary file not shown.
Before Width: | Height: | Size: 53 KiB |
Binary file not shown.
Before Width: | Height: | Size: 70 KiB |
|
@ -1,318 +0,0 @@
|
||||||
---
|
|
||||||
title: Akses Aplikasi Self-Hosted di Rumah Dari Manapun
|
|
||||||
description: Tujuan artikel ini adalah untuk menunjukkan bagaimana saya dapat mengakses foto dan video saya di rumah dari mana saja, menggunakan VPN tunnel yang terhubung ke server Immich lokal saya.
|
|
||||||
summary: Bagaimana saya dapat mengakses aplikasi Immich saya di rumah dari mana saja.
|
|
||||||
# linkTitle:
|
|
||||||
date: 2024-10-23T07:50:00+07:00
|
|
||||||
lastmod:
|
|
||||||
draft: false
|
|
||||||
noindex: false
|
|
||||||
# comments: false
|
|
||||||
nav_weight: 1000
|
|
||||||
categories:
|
|
||||||
- Self-Hosted
|
|
||||||
tags:
|
|
||||||
- Immich
|
|
||||||
- WireGuard
|
|
||||||
- Nginx
|
|
||||||
- Cloudflare
|
|
||||||
- DNS
|
|
||||||
- MikroTik
|
|
||||||
- AdGuard
|
|
||||||
images:
|
|
||||||
authors:
|
|
||||||
- ditatompel
|
|
||||||
---
|
|
||||||
|
|
||||||
Ada banyak cara untuk mengekspose _HTTP service_ yang berada dibalik NAT supaya
|
|
||||||
dapat diakses dari internet. Pada umumnya, teknik yang dilakukan adalah
|
|
||||||
melakukan _network tunnel_ menggunakan VPN dan HTTP _reverse proxy_.
|
|
||||||
[Cloudflare Tunnel][cloudflare-tunnel] adalah salah satu contoh yang
|
|
||||||
menggunakan teknik ini.
|
|
||||||
|
|
||||||
Di artikel ini saya ingin berbagi pengalaman dan cara saya mengekspose HTTP
|
|
||||||
service yang berada di jaringan lokal ke internet menggunakan WireGuard VPN
|
|
||||||
tunnel dan Nginx sebagai _HTTP reverse proxy_. HTTP service yang akan saya
|
|
||||||
expose adalah [Immich][immich-web]. Bagi yang belum tahu, Immich adalah solusi
|
|
||||||
manajemen foto dan video yang dapat dihosting sendiri; sebuah alternatif dari
|
|
||||||
[Google Photos][google-photos].
|
|
||||||
|
|
||||||
Saya tidak akan membahas detail cara menginstall Immich karena proses [instalasi Immich menggunakan Docker][immich-docker-install] sangat mudah dilakukan. Saya akan lebih fokus ke konfigurasi Nginx dan VPN tunnel, serta topologi yang digunakan.
|
|
||||||
|
|
||||||
## Prasyarat
|
|
||||||
|
|
||||||
Sebelum memulai ada beberapa kondisi yang perlu dipenuhi, yaitu:
|
|
||||||
|
|
||||||
1. Sebuah nama domain atau subdomain yang menggunakan Cloudflare sebagai
|
|
||||||
_authoritative DNS server_.
|
|
||||||
2. Sebuah VPS dengan IP public (sudah terinstall WireGuard dan Nginx yang
|
|
||||||
nantinya digunakan untuk _reverse proxy_ ke jaringan lokal).
|
|
||||||
3. Sebuah PC / VM / LXC di jaringan lokal untuk menjalankan Nginx, Docker dan
|
|
||||||
Certbot.
|
|
||||||
|
|
||||||
## Topologi
|
|
||||||
|
|
||||||
Sebelum memulai, saya ingin membagikan topologi jaringan yang saya gunakan saat
|
|
||||||
artikel ini dibuat.
|
|
||||||
|
|
||||||
![gambar topologi jaringan](topology.jpg#center)
|
|
||||||
|
|
||||||
Ijinkan saya menjelaskan topologi diatas dan memberikan tambahan informasi
|
|
||||||
untuk mengikuti artikel ini:
|
|
||||||
|
|
||||||
- Subdomain yang saya gunakan untuk Immich adalah `i.arch.or.id`.
|
|
||||||
- IP publik VPS server yang saya gunakan adalah `154.26.xxx.xx`.
|
|
||||||
- IP VPS server untuk WireGuard tunnel adalah `10.88.88.51`.
|
|
||||||
- Jaringan LAN menggunakan segmen `192.168.2.0/24`.
|
|
||||||
- Immich terinstall di LXC yang berada di jaringan lokal dengan alamat IP
|
|
||||||
`192.168.2.105`.
|
|
||||||
- LXC Immich terkoneksi ke VPS server dan menggunakan IP tunnel `10.88.88.105`.
|
|
||||||
- Di LXC Immich juga terinstall Nginx dan Certbot.
|
|
||||||
|
|
||||||
Tujuan akhir dari artikel ini adalah aplikasi Immich dapat diakses dari
|
|
||||||
internet dan seluruh perangkat yang berada pada jaringan lokal dapat terkoneksi
|
|
||||||
secara langsung ke server Immich tanpa harus memutar ke internet.
|
|
||||||
|
|
||||||
Jadi ketika saya berada di luar rumah, saya masih tetap bisa mengakses foto dan
|
|
||||||
video saya yang berada di rumah melalui aplikasi Immich. Sedangkan saat saya
|
|
||||||
berada dirumah, saya dapat secara leluasa melakukan sinkronisasi atau upload
|
|
||||||
foto dan video lebih cepat karena terkoneksi langsung menggunakan jaringan LAN.
|
|
||||||
|
|
||||||
## Konfigurasi
|
|
||||||
|
|
||||||
### Cloudflare: DNS record & Edge Certificates
|
|
||||||
|
|
||||||
Anda perlu mendelegasikan _authoritative DNS server_ ke Cloudflare kemudian
|
|
||||||
tambahkan atau arahkan `A`/`AAAA` record untuk subdomain yang akan digunakan
|
|
||||||
oleh immich ke IP public VPS Anda. Di artikel ini berarti saya mengarahkan `A`
|
|
||||||
record `i.arch.or.id` ke IP `154.26.xxx.xx`.
|
|
||||||
|
|
||||||
![](cf-dns-record.jpg#center)
|
|
||||||
|
|
||||||
Ada beberapa setting default dari Cloudflare yang perlu dirubah supaya LXC
|
|
||||||
dapat melakukan request sertifikat SSL menggunakan certbot, yaitu:
|
|
||||||
|
|
||||||
1. Mengubah **mode enkripsi** ke `Full`. Caranya masuk ke manajemen domain ->
|
|
||||||
**SSL/TLS** -> **Overview**. Pada bagian **"SSL/TLS encryption"** ubah
|
|
||||||
**_encryption mode_** ke `Full`. Hal ini perlu dilakukan supaya Cloudflare
|
|
||||||
mau menerima _"self-signed certificate"_ dari _origin server_.
|
|
||||||
![](cf-encryption-mode.jpg#center)
|
|
||||||
2. Mendisable **"Always Use HTTPS"** dan **"Automatic HTTPS Rewrites"**.
|
|
||||||
Caranya masuk ke manajemen domain -> **Edge Certificates**. Pastikan
|
|
||||||
**"Always Use HTTPS"** dan **"Automatic HTTPS Rewrites"** tidak aktif. Hal
|
|
||||||
ini perlu dilakukan supaya verifikasi SSL request dari LXC ke **Let's
|
|
||||||
Encrypt** server berjalan dengan lancar.
|
|
||||||
![](cf-automatic-https.jpg#center)
|
|
||||||
|
|
||||||
### VPS: WireGuard & Nginx
|
|
||||||
|
|
||||||
Anda perlu mensetting dan menjalankan WireGuard di VPS server yang nantinya
|
|
||||||
digunakan untuk berkomunikasi dengan LXC server yang berada di jaringan lokal.
|
|
||||||
Jika Anda belum pernah melakukan konfigurasi WireGuard, Anda dapat membaca
|
|
||||||
artikel saya sebelumnya tentang [cara setup WireGuard VPN server secara
|
|
||||||
manual]({{< ref "/tutorials/how-to-setup-your-own-wireguard-vpn-server/index.id.md" >}})
|
|
||||||
atau [menggunakan WireGuard-UI]({{< ref "/tutorials/installing-wireguard-ui-to-manage-your-wireguard-vpn-server/index.id.md" >}}).
|
|
||||||
|
|
||||||
Kurang lebih, konfigurasi WireGuard di VPS server saya sebagai berikut:
|
|
||||||
|
|
||||||
```plain
|
|
||||||
[Interface]
|
|
||||||
PrivateKey = SomeRandomStringThatShouldBePrivate
|
|
||||||
Address = 10.88.88.51/22
|
|
||||||
ListenPort = 51822
|
|
||||||
|
|
||||||
# Immich LXC server
|
|
||||||
[Peer]
|
|
||||||
PublicKey = SomeRandomStringThatPublicMayKnow
|
|
||||||
AllowedIPs = 10.88.88.105/32
|
|
||||||
```
|
|
||||||
|
|
||||||
Kemudian konfigurasi Nginx di VPS server sebagai reverse proxy ke LXC server,
|
|
||||||
kurang lebih konfigurasi Nginx saya sebagai berikut:
|
|
||||||
|
|
||||||
```nginx
|
|
||||||
upstream immich_app {
|
|
||||||
server 10.88.88.105:443;
|
|
||||||
}
|
|
||||||
|
|
||||||
server {
|
|
||||||
listen 80;
|
|
||||||
listen 443 ssl;
|
|
||||||
server_name i.arch.or.id;
|
|
||||||
|
|
||||||
# Self-signed certificates
|
|
||||||
ssl_certificate /etc/nginx/certs/fullchain.pem;
|
|
||||||
ssl_certificate_key /etc/nginx/certs/privkey.pem;
|
|
||||||
|
|
||||||
# Acme challenge handler
|
|
||||||
location /.well-known/acme-challenge/ {
|
|
||||||
allow all;
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto https;
|
|
||||||
|
|
||||||
# This avoid SSL_do_handshake() failed on HTTPS upstream
|
|
||||||
proxy_ssl_name $host;
|
|
||||||
proxy_ssl_server_name on;
|
|
||||||
proxy_ssl_verify off;
|
|
||||||
|
|
||||||
proxy_pass https://immich_app;
|
|
||||||
}
|
|
||||||
|
|
||||||
keepalive_timeout 70;
|
|
||||||
sendfile on;
|
|
||||||
client_max_body_size 100m;
|
|
||||||
|
|
||||||
location / {
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto https;
|
|
||||||
|
|
||||||
# This avoid SSL_do_handshake() failed on HTTPS upstream
|
|
||||||
proxy_ssl_name $host;
|
|
||||||
proxy_ssl_server_name on;
|
|
||||||
proxy_ssl_verify off;
|
|
||||||
|
|
||||||
# enable websockets: http://nginx.org/en/docs/http/websocket.html
|
|
||||||
proxy_http_version 1.1;
|
|
||||||
proxy_set_header Upgrade $http_upgrade;
|
|
||||||
proxy_set_header Connection "upgrade";
|
|
||||||
proxy_redirect off;
|
|
||||||
|
|
||||||
proxy_pass https://immich_app;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Bisa dilihat bahwa Nginx di VPS server menggunakan _Self-signed certificates_.
|
|
||||||
Hal ini tidak menjadi masalah karena kita sudah mengkonfigurasi Cloudflare
|
|
||||||
SSL/TLS **encryption mode** ke `Full`.
|
|
||||||
|
|
||||||
Dengan konfigurasi diatas, _HTTP request_ dari internet akan melewati
|
|
||||||
Cloudflare dan menggunakan sertifikat SSL yang valid dari Cloudflare. Request
|
|
||||||
dilanjutkan ke VPS server dan kemudian diteruskan ke LXC server melalui
|
|
||||||
WireGuard VPN tunnel.
|
|
||||||
|
|
||||||
### Lokal LXC: WireGuard, Immich (Docker), Nginx, Certbot
|
|
||||||
|
|
||||||
Install WireGuard dan buat konfigurasi supaya bisa terhubung ke WireGuard
|
|
||||||
server di VPS. Berikut ini contoh konfigurasi WireGuard di LXC server saya:
|
|
||||||
|
|
||||||
```plain
|
|
||||||
[Interface]
|
|
||||||
PrivateKey = SomeRandomStringThatShouldBePrivateII
|
|
||||||
Address = 10.88.88.105/22
|
|
||||||
|
|
||||||
# VPS server
|
|
||||||
[Peer]
|
|
||||||
PublicKey = SomeRandomStringThatPublicMayKnowII
|
|
||||||
AllowedIPs = 10.88.88.51/32
|
|
||||||
Endpoint = 154.26.xxx.xxx:51822
|
|
||||||
PersistentKeepalive = 15
|
|
||||||
```
|
|
||||||
|
|
||||||
Kemudian, install Immich dengan mengikuti proses [instalasi Immich menggunakan
|
|
||||||
Docker dari situs resminya][immich-docker-install]. Secara default, Immich akan
|
|
||||||
menggunakan TCP port `2283`.
|
|
||||||
|
|
||||||
Buat konfigurasi Nginx virtual host untuk Immich. Nginx di LXC ini akan
|
|
||||||
berfungsi sebagai reverse proxy dan menghandle **Acme challenge** sehingga
|
|
||||||
server LXC memiliki sertifikat yang valid. Berikut ini adalah contoh
|
|
||||||
konfigurasi Nginx virtual host untuk Immich di server LXC lokal:
|
|
||||||
|
|
||||||
```nginx
|
|
||||||
upstream immich_app {
|
|
||||||
server 127.0.0.1:2283;
|
|
||||||
}
|
|
||||||
|
|
||||||
server {
|
|
||||||
listen 80;
|
|
||||||
server_name i.arch.or.id;
|
|
||||||
root /srv/http/default;
|
|
||||||
|
|
||||||
location /.well-known/acme-challenge/ {
|
|
||||||
allow all;
|
|
||||||
}
|
|
||||||
location / { return 301 https://$host$request_uri; }
|
|
||||||
}
|
|
||||||
|
|
||||||
server {
|
|
||||||
listen 443 ssl;
|
|
||||||
server_name i.arch.or.id;
|
|
||||||
ssl_certificate /etc/nginx/certs/fullchain.pem;
|
|
||||||
ssl_certificate_key /etc/nginx/certs/privkey.pem;
|
|
||||||
|
|
||||||
# allow large file uploads
|
|
||||||
client_max_body_size 50000M;
|
|
||||||
|
|
||||||
location / {
|
|
||||||
# Set headers
|
|
||||||
proxy_set_header Host $http_host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
|
|
||||||
# enable websockets: http://nginx.org/en/docs/http/websocket.html
|
|
||||||
proxy_http_version 1.1;
|
|
||||||
proxy_set_header Upgrade $http_upgrade;
|
|
||||||
proxy_set_header Connection "upgrade";
|
|
||||||
proxy_redirect off;
|
|
||||||
|
|
||||||
proxy_pass http://immich_app;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Dari konfigurasi Nginx diatas, perlu diperhatikan bahwa untuk konfigurasi awal
|
|
||||||
saya masih menggunakan _Self-signed certificate_. Langkah selanjutnya adalah
|
|
||||||
melakukan request sertifikat SSL menggunakan Certbot.
|
|
||||||
|
|
||||||
> **Catatan**: Sebelum melakukan request serifikat SSL, pastikan koneksi antara
|
|
||||||
> VPS server dan LXC melalui WireGuard tunnel berjalan dengan baik. Begitu pula
|
|
||||||
> dengan konfigurasi Nginx baik di VPS server dan LXC server.
|
|
||||||
|
|
||||||
Install certbot Nginx plugin. Di Ubuntu, Anda bisa menginstall cerbot Nginx
|
|
||||||
plugin menggunakan `sudo apt install python3-certbot-nginx`. Setelah Certbot
|
|
||||||
Nginx plugin terinstall, lakukan request sertifikat SSL dari XLC server:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
sudo certbot --nginx -d i.arch.or.id
|
|
||||||
```
|
|
||||||
|
|
||||||
Ubah `i.arch.or.id` ke (sub)domain milik Anda.
|
|
||||||
|
|
||||||
### LAN: Lokal DNS resolver
|
|
||||||
|
|
||||||
Langkah terakhir adalah mengkonfigurasi perangkat-perangkat di jaringan LAN
|
|
||||||
supaya subdomain `i.arch.or.id` mengarah ke IP lokal server LXC
|
|
||||||
(192.169.2.105). Cara paling efektif adalah menggunakan lokal _DNS resolver_
|
|
||||||
yang bisa digunakan oleh seluruh perangkat di jaringan LAN. Untuk konfigurasi
|
|
||||||
_DNS resolver_ akan sangat bervariasi tergantung seperti apa jaringan LAN
|
|
||||||
masing-masing.
|
|
||||||
|
|
||||||
Untuk jaringan LAN saya, saya mempunyai dua buah DNS resolver. DNS resolver
|
|
||||||
pertama berada di Router **MikroTik**, dan resolver kedua menggunakan
|
|
||||||
**AdGuard Home** yang berjalan di Linux Container. AdGuard home disini saya
|
|
||||||
gunakan juga sebagai DHCP server untuk jaringan lokal saya.
|
|
||||||
|
|
||||||
Berikut capture konfigurasi DNS resolver di MikroTik router dan AdGuard Home
|
|
||||||
saya:
|
|
||||||
|
|
||||||
![](lan-dns-resolver.jpg#center)
|
|
||||||
|
|
||||||
Dengan konfigurasi tersebut, seluruh perangkat yang ada di jaringan lokal
|
|
||||||
menggunakan DHCP akan langsung akan menggunakan IP `192.168.2.105` ketika
|
|
||||||
mencoba mengakses subdomain `i.arch.or.id`.
|
|
||||||
|
|
||||||
## limitasi
|
|
||||||
|
|
||||||
- Karena maksimum upload di Cloudflare hanya 100MB per request (untuk free
|
|
||||||
version), maka proses sinkronisasi Immich dari internet kemungkinan besar
|
|
||||||
banyak yang gagal, terutama saat sinkronisasi video.
|
|
||||||
|
|
||||||
[cloudflare-tunnel]: https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/ "Cloudflare Tunnel"
|
|
||||||
[immich-web]: https://immich.app/ "Immich website"
|
|
||||||
[immich-docker-install]: https://immich.app/docs/install/docker-compose "Install Immich using Docker"
|
|
||||||
[google-photos]: https://photos.google.com/ "Google Photos website"
|
|
|
@ -1,315 +0,0 @@
|
||||||
---
|
|
||||||
title: Access Any Self-Hosted Applications at Home From Anywhere
|
|
||||||
description: The goal of this article is to demonstrate how I can access my photos and videos at home from anywhere, using a network tunnel to connect to my local Immich server.
|
|
||||||
summary: How I can access my Immich application at home from anywhere.
|
|
||||||
# linkTitle:
|
|
||||||
date: 2024-10-23T07:50:00+07:00
|
|
||||||
lastmod:
|
|
||||||
draft: false
|
|
||||||
noindex: false
|
|
||||||
# comments: false
|
|
||||||
nav_weight: 1000
|
|
||||||
categories:
|
|
||||||
- Self-Hosted
|
|
||||||
tags:
|
|
||||||
- Immich
|
|
||||||
- WireGuard
|
|
||||||
- Nginx
|
|
||||||
- Cloudflare
|
|
||||||
- DNS
|
|
||||||
- MikroTik
|
|
||||||
- AdGuard
|
|
||||||
images:
|
|
||||||
authors:
|
|
||||||
- ditatompel
|
|
||||||
---
|
|
||||||
|
|
||||||
There are many ways to expose HTTP services behind NAT so that they can be
|
|
||||||
accessed from the internet. The technique commonly employed involves setting
|
|
||||||
up a network tunnel using VPN and an HTTP reverse proxy. [Cloudflare
|
|
||||||
Tunnel][cloudflare-tunnel] is one example.
|
|
||||||
|
|
||||||
In this article, I want to share my experience and how I expose HTTP services
|
|
||||||
on a local network to the internet using WireGuard VPN tunnel and Nginx as an
|
|
||||||
HTTP reverse proxy. The HTTP service I will expose is [Immich][immich-web].
|
|
||||||
For those who don't know, Immich is a self-hosted photo and video management
|
|
||||||
solution; an alternative to [Google Photos][google-photos].
|
|
||||||
|
|
||||||
I won't discuss the details of how to install Immich because [installing Immich
|
|
||||||
using Docker][immich-docker-install] is very easy to do. Instead, I'll focus on
|
|
||||||
the configuration of Nginx and VPN tunnel, as well as the [topology
|
|
||||||
used](#topology).
|
|
||||||
|
|
||||||
## Prerequisites
|
|
||||||
|
|
||||||
Before we get started, there are a few conditions that need to be met:
|
|
||||||
|
|
||||||
1. A domain name or subdomain that uses Cloudflare as its authoritative DNS
|
|
||||||
server.
|
|
||||||
2. A VPS with a public IP address (WireGuard and Nginx installed, which will
|
|
||||||
later be used for reverse proxying the local network).
|
|
||||||
3. A PC, VM, or LXC on the local network to run Immich, Nginx, Docker, and
|
|
||||||
Certbot.
|
|
||||||
|
|
||||||
## Topology
|
|
||||||
|
|
||||||
When writing this article, I used the following network topology:
|
|
||||||
|
|
||||||
![network topology image](topology.jpg#center)
|
|
||||||
|
|
||||||
To provide further context, let me break down the components of the above
|
|
||||||
topology:
|
|
||||||
|
|
||||||
- The subdomain used for Immich is `i.arch.or.id`.
|
|
||||||
- The public IP address of the VPS server is `154.26.xxx.xx`.
|
|
||||||
- The VPS server's WireGuard tunnel IP address is `10.88.88.51`.
|
|
||||||
- The local area network (LAN) uses the `192.168.2.0/24` subnet.
|
|
||||||
- Immich is installed on an LXC container located on the local network,
|
|
||||||
with an IP address of `192.168.2.105`.
|
|
||||||
- The Immich LXC is connected to the VPS server and utilizes the IP tunnel
|
|
||||||
`10.88.88.105`.
|
|
||||||
- Nginx and Certbot are also installed on the Immich LXC.
|
|
||||||
|
|
||||||
The ultimate goal of this article is to demonstrate how I can access my photos
|
|
||||||
and videos at home from anywhere, using a network tunnel to connect to my local
|
|
||||||
Immich server. This setup allows me to synchronize or upload files faster when
|
|
||||||
I'm at home, while still being able to access my media remotely through the
|
|
||||||
Immich application.
|
|
||||||
|
|
||||||
## Configuration
|
|
||||||
|
|
||||||
### Cloudflare: DNS records & Edge Certificates
|
|
||||||
|
|
||||||
To configure Cloudflare, you need to delegate the authoritative DNS server and
|
|
||||||
add or point the `A`/`AAAA` record for the subdomain that will be used by
|
|
||||||
Immich to your VPS public IP. In this article, I pointed the `A` record
|
|
||||||
`i.arch.or.id` to the IP `154.26.xxx.xx`.
|
|
||||||
|
|
||||||
![](cf-dns-record.jpg#center)
|
|
||||||
|
|
||||||
To ensure that LXC on your local network can make a smooth request for SSL
|
|
||||||
certificates using Certbot, you'll need to modify several default Cloudflare
|
|
||||||
settings:
|
|
||||||
|
|
||||||
1. Update the **encryption mode** to `Full`. To do this, navigate to domain
|
|
||||||
management -> **SSL/TLS** -> **Overview**, and modify the **"SSL/TLS
|
|
||||||
encryption"** to `Full`. This is necessary for Cloudflare to accept the
|
|
||||||
_"self-signed certificate"_ from the _origin server_.
|
|
||||||
![](cf-encryption-mode.jpg#center)
|
|
||||||
2. Disable both **"Always Use HTTPS"** and **"Automatic HTTPS Rewrites"**. To
|
|
||||||
achieve this, go to domain management -> **Edge Certificates**, and ensure
|
|
||||||
that these features are not active. This is necessary for the SSL request
|
|
||||||
verification from LXC to the **Let's Encrypt** server to run smoothly.
|
|
||||||
![](cf-automatic-https.jpg#center)
|
|
||||||
|
|
||||||
### VPS: WireGuard & Nginx
|
|
||||||
|
|
||||||
You need to set up and run WireGuard on the VPS server which will be used to
|
|
||||||
communicate with the LXC server on the local network. If you're new to
|
|
||||||
WireGuard configuration, I recommend reviewing my previous articles on [setting
|
|
||||||
up a WireGuard VPN server manually]({{< ref "/tutorials/how-to-setup-your-own-wireguard-vpn-server/index.id.md" >}})
|
|
||||||
or [using WireGuard-UI]({{< ref "/tutorials/installing-wireguard-ui-to-manage-your-wireguard-vpn-server/index.id.md" >}}).
|
|
||||||
|
|
||||||
Here's an example of my WireGuard configuration on my VPS server:
|
|
||||||
|
|
||||||
```plain
|
|
||||||
[Interface]
|
|
||||||
PrivateKey = SomeRandomStringThatShouldBePrivate
|
|
||||||
Address = 10.88.88.51/22
|
|
||||||
ListenPort = 51822
|
|
||||||
|
|
||||||
# Immich LXC server
|
|
||||||
[Peer]
|
|
||||||
PublicKey = SomeRandomStringThatPublicMayKnow
|
|
||||||
AllowedIPs = 10.88.88.105/32
|
|
||||||
```
|
|
||||||
|
|
||||||
Next, I configured Nginx on the VPS server as a reverse proxy to the LXC
|
|
||||||
server. My Nginx configuration is similar to the following:
|
|
||||||
|
|
||||||
```nginx
|
|
||||||
upstream immich_app {
|
|
||||||
server 10.88.88.105:443;
|
|
||||||
}
|
|
||||||
|
|
||||||
server {
|
|
||||||
listen 80;
|
|
||||||
listen 443 ssl;
|
|
||||||
server_name i.arch.or.id;
|
|
||||||
|
|
||||||
# Self-signed certificates
|
|
||||||
ssl_certificate /etc/nginx/certs/fullchain.pem;
|
|
||||||
ssl_certificate_key /etc/nginx/certs/privkey.pem;
|
|
||||||
|
|
||||||
# Acme challenge handler
|
|
||||||
location /.well-known/acme-challenge/ {
|
|
||||||
allow all;
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto https;
|
|
||||||
|
|
||||||
# This avoid SSL_do_handshake() failed on HTTPS upstream
|
|
||||||
proxy_ssl_name $host;
|
|
||||||
proxy_ssl_server_name on;
|
|
||||||
proxy_ssl_verify off;
|
|
||||||
|
|
||||||
proxy_pass https://immich_app;
|
|
||||||
}
|
|
||||||
|
|
||||||
keepalive_timeout 70;
|
|
||||||
sendfile on;
|
|
||||||
client_max_body_size 100m;
|
|
||||||
|
|
||||||
location / {
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto https;
|
|
||||||
|
|
||||||
# This avoid SSL_do_handshake() failed on HTTPS upstream
|
|
||||||
proxy_ssl_name $host;
|
|
||||||
proxy_ssl_server_name on;
|
|
||||||
proxy_ssl_verify off;
|
|
||||||
|
|
||||||
# enable websockets: http://nginx.org/en/docs/http/websocket.html
|
|
||||||
proxy_http_version 1.1;
|
|
||||||
proxy_set_header Upgrade $http_upgrade;
|
|
||||||
proxy_set_header Connection "upgrade";
|
|
||||||
proxy_redirect off;
|
|
||||||
|
|
||||||
proxy_pass https://immich_app;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
It's worth noting that Nginx virtual host configuration for `i.arch.or.id` on
|
|
||||||
the VPS server uses _Self-signed certificates_ for SSL/TLS encryption. This
|
|
||||||
isn't an issue, as we've previously configured Cloudflare's SSL/TLS
|
|
||||||
**encryption mode** to `Full`.
|
|
||||||
|
|
||||||
With this configuration in place, HTTP requests from the internet are routed
|
|
||||||
through Cloudflare and utilize a valid SSL certificate from Cloudflare. The
|
|
||||||
request is then forwarded to the VPS server and subsequently to the LXC server
|
|
||||||
via the WireGuard VPN tunnel.
|
|
||||||
|
|
||||||
### Local LXC: WireGuard, Immich (Docker), Nginx, Certbot
|
|
||||||
|
|
||||||
Install WireGuard and configure it to connect to the WireGuard server on the
|
|
||||||
VPS. Here's an example of my WireGuard configuration on my LXC server:
|
|
||||||
|
|
||||||
```plain
|
|
||||||
[Interface]
|
|
||||||
PrivateKey = SomeRandomStringThatShouldBePrivateII
|
|
||||||
Address = 10.88.88.105/22
|
|
||||||
|
|
||||||
# VPS server
|
|
||||||
[Peer]
|
|
||||||
PublicKey = SomeRandomStringThatPublicMayKnowII
|
|
||||||
AllowedIPs = 10.88.88.51/32
|
|
||||||
Endpoint = 154.26.xxx.xxx:51822
|
|
||||||
PersistentKeepalive = 15
|
|
||||||
```
|
|
||||||
|
|
||||||
Next, install Immich by following the process outlined on its official website
|
|
||||||
for [installing Immich using Docker][immich-docker-install]. By default,
|
|
||||||
Immich will use TCP port `2283`.
|
|
||||||
|
|
||||||
Create an Nginx virtual host configuration for Immich. On my local LXC server,
|
|
||||||
Nginx will function as a reverse proxy and handle Acme challenges to obtain a
|
|
||||||
valid certificate. Here's an example of the Nginx virtual host configuration
|
|
||||||
for Immich:
|
|
||||||
|
|
||||||
```nginx
|
|
||||||
upstream immich_app {
|
|
||||||
server 127.0.0.1:2283;
|
|
||||||
}
|
|
||||||
|
|
||||||
server {
|
|
||||||
listen 80;
|
|
||||||
server_name i.arch.or.id;
|
|
||||||
root /srv/http/default;
|
|
||||||
|
|
||||||
location /.well-known/acme-challenge/ {
|
|
||||||
allow all;
|
|
||||||
}
|
|
||||||
location / { return 301 https://$host$request_uri; }
|
|
||||||
}
|
|
||||||
|
|
||||||
server {
|
|
||||||
listen 443 ssl;
|
|
||||||
server_name i.arch.or.id;
|
|
||||||
ssl_certificate /etc/nginx/certs/fullchain.pem;
|
|
||||||
ssl_certificate_key /etc/nginx/certs/privkey.pem;
|
|
||||||
|
|
||||||
# allow large file uploads
|
|
||||||
client_max_body_size 50000M;
|
|
||||||
|
|
||||||
location / {
|
|
||||||
# Set headers
|
|
||||||
proxy_set_header Host $http_host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
|
|
||||||
# enable websockets: http://nginx.org/en/docs/http/websocket.html
|
|
||||||
proxy_http_version 1.1;
|
|
||||||
proxy_set_header Upgrade $http_upgrade;
|
|
||||||
proxy_set_header Connection "upgrade";
|
|
||||||
proxy_redirect off;
|
|
||||||
|
|
||||||
proxy_pass http://immich_app;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
From the configuration above, it is clear that I initially uses a self-signed
|
|
||||||
certificate. Later, the certificate will be automatically replaced with a valid
|
|
||||||
one from Let's Encrypt, utilizing Certbot.
|
|
||||||
|
|
||||||
> **Note**: Before requesting an SSL certificate, ensure that the connection
|
|
||||||
> between the VPS server and LXC via the WireGuard tunnel is running smoothly.
|
|
||||||
> Also, verify that the Nginx configuration on both the VPS server and LXC
|
|
||||||
> server is correctly set up.
|
|
||||||
|
|
||||||
Install the Certbot Nginx plugin. On Ubuntu-based systems, you can install the
|
|
||||||
certbot Nginx plugin using `sudo apt install python3-certbot-nginx`. After
|
|
||||||
installing the plugin, request an SSL certificate from the XLC server:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
sudo certbot --nginx -d i.arch.or.id
|
|
||||||
```
|
|
||||||
|
|
||||||
Replace `i.arch.or.id` with your (sub)domain.
|
|
||||||
|
|
||||||
### LAN: Local DNS resolver
|
|
||||||
|
|
||||||
The final step is to configure devices on the local area network (LAN) so that
|
|
||||||
the subdomain `i.arch.or.id` resolves to the local IP address of the LXC server
|
|
||||||
(`192.168.2.105`). A reliable approach is to use a local DNS resolver that can
|
|
||||||
be utilized by all devices within the LAN network. The configuration for this
|
|
||||||
DNS resolver will depend on the specific characteristics of each LAN network.
|
|
||||||
|
|
||||||
For my LAN setup, I have two DNS resolvers. The first one is located on my
|
|
||||||
Router (MikroTik), and the second is AdGuard Home running on a Linux Container.
|
|
||||||
In addition, I utilize AdGuard home as a DHCP server for my local network.
|
|
||||||
|
|
||||||
Here's a capture of the DNS resolver configuration on my MikroTik router and
|
|
||||||
AdGuard Home:
|
|
||||||
|
|
||||||
![](lan-dns-resolver.jpg#center)
|
|
||||||
|
|
||||||
With this setup, all devices on the local network that obtain their IP
|
|
||||||
addresses via DHCP will immediately use the IP `192.168.2.105` when attempting
|
|
||||||
to access the subdomain `i.arch.or.id`.
|
|
||||||
|
|
||||||
## Limitations
|
|
||||||
|
|
||||||
- Due to the 100MB per request upload limit imposed by Cloudflare (for its
|
|
||||||
free version), the Immich synchronization process from the internet is
|
|
||||||
likely to fail, particularly when synchronizing videos.
|
|
||||||
|
|
||||||
[cloudflare-tunnel]: https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/ "Cloudflare Tunnel"
|
|
||||||
[immich-web]: https://immich.app/ "Immich website"
|
|
||||||
[immich-docker-install]: https://immich.app/docs/install/docker-compose "Install Immich using Docker"
|
|
||||||
[google-photos]: https://photos.google.com/ "Google Photos website"
|
|
Binary file not shown.
Before Width: | Height: | Size: 115 KiB |
Binary file not shown.
Before Width: | Height: | Size: 109 KiB |
4
go.mod
4
go.mod
|
@ -71,8 +71,8 @@ require (
|
||||||
github.com/hugomods/hugopress v0.5.0 // indirect
|
github.com/hugomods/hugopress v0.5.0 // indirect
|
||||||
github.com/hugomods/i18n-js v0.2.1 // indirect
|
github.com/hugomods/i18n-js v0.2.1 // indirect
|
||||||
github.com/hugomods/icons v0.6.5 // indirect
|
github.com/hugomods/icons v0.6.5 // indirect
|
||||||
github.com/hugomods/icons/vendors/bootstrap v0.5.8 // indirect
|
github.com/hugomods/icons/vendors/bootstrap v0.5.7 // indirect
|
||||||
github.com/hugomods/icons/vendors/font-awesome v0.6.9 // indirect
|
github.com/hugomods/icons/vendors/font-awesome v0.6.8 // indirect
|
||||||
github.com/hugomods/icons/vendors/simple-icons v1.0.58 // indirect
|
github.com/hugomods/icons/vendors/simple-icons v1.0.58 // indirect
|
||||||
github.com/hugomods/idb-js v0.1.0 // indirect
|
github.com/hugomods/idb-js v0.1.0 // indirect
|
||||||
github.com/hugomods/images v0.11.2 // indirect
|
github.com/hugomods/images v0.11.2 // indirect
|
||||||
|
|
11
go.sum
11
go.sum
|
@ -134,11 +134,12 @@ github.com/hugomods/i18n-js v0.2.1 h1:uIUl4LiYdwo8IK08oq7OmluYLedL21Wc9Rig1taDTS
|
||||||
github.com/hugomods/i18n-js v0.2.1/go.mod h1:eJfxjgI2CQsNA1/ReIVvr5127DftUKcbHd2A2SQmDvU=
|
github.com/hugomods/i18n-js v0.2.1/go.mod h1:eJfxjgI2CQsNA1/ReIVvr5127DftUKcbHd2A2SQmDvU=
|
||||||
github.com/hugomods/icons v0.6.5 h1:vuaBlVO/MTsQNir4JWvPazjmtMMWG55Lif6VHCmd7KI=
|
github.com/hugomods/icons v0.6.5 h1:vuaBlVO/MTsQNir4JWvPazjmtMMWG55Lif6VHCmd7KI=
|
||||||
github.com/hugomods/icons v0.6.5/go.mod h1:cIkSvK6W0q6N4U6n9KGz+QfRWQXAW0INd+1P31gPNGg=
|
github.com/hugomods/icons v0.6.5/go.mod h1:cIkSvK6W0q6N4U6n9KGz+QfRWQXAW0INd+1P31gPNGg=
|
||||||
github.com/hugomods/icons/vendors/bootstrap v0.5.8 h1:6M+G4F58pt3GkiGFeCDjKonExVV8PbBAVhDS8YQT7oY=
|
github.com/hugomods/icons/vendors/bootstrap v0.5.7 h1:k2oXx7EOqiqPv9SRb2mtSiPtdWMQUFhtwE3kd0+5QK4=
|
||||||
github.com/hugomods/icons/vendors/bootstrap v0.5.8/go.mod h1:jla3IbQAByyz45AikUAw/c7h0wUMUn5Z2j4gh+zVDj4=
|
github.com/hugomods/icons/vendors/bootstrap v0.5.7/go.mod h1:bTxiIPJ/idHEc35EtvtwSODLpjI+R54BkGdikO3gCmY=
|
||||||
github.com/hugomods/icons/vendors/font-awesome v0.6.9 h1:ZpnyXeCOa9n7NBVURSRIZuGZykz80udHT8yxM+RE6NQ=
|
github.com/hugomods/icons/vendors/font-awesome v0.6.8 h1:wcqovckhWxcYTkOn4JOp2HljVmus+59AwDP9cAYWiMg=
|
||||||
github.com/hugomods/icons/vendors/font-awesome v0.6.9/go.mod h1:YPxdyI0WHuZfvwNeG8ADHXwnWmWIuu3PqiYGz8q9Skw=
|
github.com/hugomods/icons/vendors/font-awesome v0.6.8/go.mod h1:IwJEJX8eFwDFCcxMjFBIgVWlPTf16yFVk78Rc3RUBjs=
|
||||||
github.com/hugomods/icons/vendors/simple-icons v1.0.58 h1:HAw65rHyKmCkjUf/+HaiU4awkD24ngfodNYtlmkBvc8=
|
github.com/hugomods/icons/vendors/simple-icons v1.0.57 h1:Y94q3o80JOMprM6axQyGdrSbuvFes7Pzco8uwMrTp/w=
|
||||||
|
github.com/hugomods/icons/vendors/simple-icons v1.0.57/go.mod h1:QNKkX7+q1fzI51xUGX4qmA11b6B+xTXZ8UMHJAKQEhY=
|
||||||
github.com/hugomods/icons/vendors/simple-icons v1.0.58/go.mod h1:FNv3PHfJQi+Ri6tPkwjmpoCb437VqyWZdrLxO6VfmTk=
|
github.com/hugomods/icons/vendors/simple-icons v1.0.58/go.mod h1:FNv3PHfJQi+Ri6tPkwjmpoCb437VqyWZdrLxO6VfmTk=
|
||||||
github.com/hugomods/idb-js v0.1.0 h1:mA6hEGtR0aFEdmq9zYMGpfSpCU6SMilx9RzC4uK3DqY=
|
github.com/hugomods/idb-js v0.1.0 h1:mA6hEGtR0aFEdmq9zYMGpfSpCU6SMilx9RzC4uK3DqY=
|
||||||
github.com/hugomods/idb-js v0.1.0/go.mod h1:GPfnmr+BQpP4s6Epd4Yu+RlUog8q/Djw8qy8BZFWZ04=
|
github.com/hugomods/idb-js v0.1.0/go.mod h1:GPfnmr+BQpP4s6Epd4Yu+RlUog8q/Djw8qy8BZFWZ04=
|
||||||
|
|
Loading…
Reference in a new issue