mirror of
https://github.com/skoobasteeve/skoobasteeve.github.io.2.git
synced 2026-03-20 07:58:57 +00:00
Compare commits
15 Commits
first-post
...
e744855dcf
| Author | SHA1 | Date | |
|---|---|---|---|
|
e744855dcf
|
|||
|
9796edbd9c
|
|||
|
e381e5adbf
|
|||
|
aa4bba1b72
|
|||
|
01fa59afa6
|
|||
|
021b15423a
|
|||
|
|
55c9d64b8c | ||
|
0bb96f6308
|
|||
|
8732edbd28
|
|||
|
650654002c
|
|||
|
e7269c40cd
|
|||
|
73f02fc964
|
|||
|
cbe5b72833
|
|||
|
4db791aa02
|
|||
|
|
073651bb8a |
16
.devcontainer/devcontainer.json
Normal file
16
.devcontainer/devcontainer.json
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"image": "mcr.microsoft.com/devcontainers/jekyll:bookworm",
|
||||
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
"extensions": [
|
||||
"albert.TabOut",
|
||||
"ecmel.vscode-html-css",
|
||||
"redhat.vscode-yaml",
|
||||
"rebornix.Ruby"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
"forwardPorts": [4000]
|
||||
}
|
||||
2
404.html
2
404.html
@@ -20,6 +20,6 @@ layout: default
|
||||
<div class="container">
|
||||
<h1>404</h1>
|
||||
|
||||
<p><strong>Page not found :(</strong></p>
|
||||
<p><strong>Page not found</strong></p>
|
||||
<p>The requested page could not be found.</p>
|
||||
</div>
|
||||
|
||||
30
Gemfile.lock
30
Gemfile.lock
@@ -1,25 +1,25 @@
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
addressable (2.8.1)
|
||||
addressable (2.8.5)
|
||||
public_suffix (>= 2.0.2, < 6.0)
|
||||
colorator (1.1.0)
|
||||
concurrent-ruby (1.1.10)
|
||||
concurrent-ruby (1.2.2)
|
||||
em-websocket (0.5.3)
|
||||
eventmachine (>= 0.12.9)
|
||||
http_parser.rb (~> 0)
|
||||
eventmachine (1.2.7)
|
||||
faraday (2.7.2)
|
||||
faraday (2.7.10)
|
||||
faraday-net_http (>= 2.0, < 3.1)
|
||||
ruby2_keywords (>= 0.0.4)
|
||||
faraday-net_http (3.0.2)
|
||||
ffi (1.15.5)
|
||||
forwardable-extended (2.6.0)
|
||||
google-protobuf (3.21.12-x86_64-linux)
|
||||
google-protobuf (3.24.0-x86_64-linux)
|
||||
http_parser.rb (0.8.0)
|
||||
i18n (1.12.0)
|
||||
i18n (1.14.1)
|
||||
concurrent-ruby (~> 1.0)
|
||||
jekyll (4.3.1)
|
||||
jekyll (4.3.2)
|
||||
addressable (~> 2.4)
|
||||
colorator (~> 1.0)
|
||||
em-websocket (~> 0.5)
|
||||
@@ -52,8 +52,8 @@ GEM
|
||||
rexml
|
||||
kramdown-parser-gfm (1.1.0)
|
||||
kramdown (~> 2.0)
|
||||
liquid (4.0.3)
|
||||
listen (3.7.1)
|
||||
liquid (4.0.4)
|
||||
listen (3.8.0)
|
||||
rb-fsevent (~> 0.10, >= 0.10.3)
|
||||
rb-inotify (~> 0.9, >= 0.9.10)
|
||||
mercenary (0.4.0)
|
||||
@@ -69,23 +69,23 @@ GEM
|
||||
sawyer (~> 0.9)
|
||||
pathutil (0.16.2)
|
||||
forwardable-extended (~> 2.6)
|
||||
public_suffix (5.0.1)
|
||||
public_suffix (5.0.3)
|
||||
rb-fsevent (0.11.2)
|
||||
rb-inotify (0.10.1)
|
||||
ffi (~> 1.0)
|
||||
rexml (3.2.5)
|
||||
rouge (4.0.1)
|
||||
rexml (3.2.6)
|
||||
rouge (4.1.3)
|
||||
ruby2_keywords (0.0.5)
|
||||
safe_yaml (1.0.5)
|
||||
sass-embedded (1.57.1-x86_64-linux-gnu)
|
||||
google-protobuf (~> 3.21)
|
||||
sass-embedded (1.64.2-x86_64-linux-gnu)
|
||||
google-protobuf (~> 3.23)
|
||||
sawyer (0.9.2)
|
||||
addressable (>= 2.3.5)
|
||||
faraday (>= 0.17.3, < 3)
|
||||
terminal-table (3.0.2)
|
||||
unicode-display_width (>= 1.1.1, < 3)
|
||||
unicode-display_width (2.4.2)
|
||||
webrick (1.7.0)
|
||||
webrick (1.8.1)
|
||||
|
||||
PLATFORMS
|
||||
x86_64-linux
|
||||
@@ -97,4 +97,4 @@ DEPENDENCIES
|
||||
webrick
|
||||
|
||||
BUNDLED WITH
|
||||
2.4.3
|
||||
2.4.18
|
||||
|
||||
@@ -23,7 +23,7 @@ name : "Ray Lyon"
|
||||
description : "Linux, self-hosting, and privacy."
|
||||
url : "https://rayagainstthemachine.net"
|
||||
baseurl : # the subpath of your site, e.g. "/blog"
|
||||
repository : "skoobasteeve/skoobasteeve.github.io.2"
|
||||
repository : "skoobasteeve/rayagainstthemachine.net"
|
||||
teaser : # path of fallback teaser image, e.g. "/assets/images/500x300.png"
|
||||
logo : # path of logo image to display in the masthead, e.g. "/assets/images/88x88.png"
|
||||
masthead_title : # overrides the website title displayed in the masthead, use " " for no title
|
||||
@@ -100,7 +100,7 @@ author:
|
||||
url: "https://keybase.io/scubasteve/pgp_keys.asc?fingerprint=2dc3a1066bba7040fe7963d9e20106cb86fe0b4d"
|
||||
- label: "Email"
|
||||
icon: "fas fa-fw fa-envelope-square"
|
||||
url: "mailto:ray@raylyon.net"
|
||||
url: "mailto:ray@rayagainstthemachine.net"
|
||||
- label: "Keybase"
|
||||
icon: "fab fa-fw fa-keybase"
|
||||
url: "https://keybase.io/scubasteve"
|
||||
|
||||
75
_posts/2023-08-27-nextcloud-podman.md
Normal file
75
_posts/2023-08-27-nextcloud-podman.md
Normal file
@@ -0,0 +1,75 @@
|
||||
---
|
||||
layout: single
|
||||
title: "Building a Reproducible Nextcloud Server, Part one: Choosing the stack"
|
||||
date: 2023-08-27 10:00:00
|
||||
excerpt: "After successfully hosting a Nextcloud instance on the same VPS for 7 years, I decided to rebuild it from scratch with modern tooling."
|
||||
categories: [Self-Hosting, Linux Administration]
|
||||
tags: linux nextcloud podman docker container vps
|
||||
comments: true
|
||||
---
|
||||
|
||||
Nextcloud was the first application I *really* self-hosted. I don't mean self-hosting like running the Plex app in the system tray on your gaming PC; I mean a dedicated VPS, exposed to the world, hosting my personal data. The stakes were high, and over the last seven years, it pushed me to grow my Linux knowledge and ultimately made me a far better sysadmin.
|
||||
|
||||
A lot happened during that seven years. Containers and infrastructure-as-code blew up and changed the IT industry. Nextcloud as a company and an application grew tremendously. I got married. Throughout all these changes, my little $5 DigitalOcean droplet running Nextcloud on the LAMP stack kept right on ticking. Despite three OS upgrades, two volume expansions, and fifteen(!) Nextcloud major-version upgrades, that thing refused to die. It continued to host my (and my wife's) critical data until the day I decommissioned it just under 60 days ago.
|
||||
|
||||
# Why change?
|
||||
|
||||
As a sysadmin and a huge Linux nerd, I'd been following the technology and industry changes closely, and every time I heard about something new or read a blog post I couldn't help but wonder "if I rebuilt my Nextcloud server today, how would I do it?". Everything is a container now, and infrastructure and system configuration is all defined as text files, making it reproducible and popularizing the phrase "cattle, not pets". I wanted a chance to embrace these concepts and use the skills I spent the last seven years improving. Plus, what sysadmin doesn't like playing with the new shiny?
|
||||
|
||||
# Goals
|
||||
|
||||
So what did I want to accomplish with this change?
|
||||
|
||||
1. **Cutting-edge technologies** - Not only did I want to play with the latest tools, I wanted to become proficient with them by putting them into production.
|
||||
2. **Reproducibility** - Use infrastructure-as-code tooling so I could spin up the whole stack and tear it back down with only a few commands.
|
||||
3. **Reliability** - Whatever combination of hardware and technologies I ended up with, it needed to be absolutely rock-solid. The only reason this thing should break is if I tell it to (intentionally or not)
|
||||
|
||||
# Hosting provider
|
||||
|
||||
I chose DigitalOcean back in 2016 mainly due to its excellent guides and popularity around the Jupiter Broadcasting community (got that sweet $100 promo code!). It was much easier to use than most other VPS providers and could have you up-and-running with an Ubuntu server and a public IP in minutes. In 2023, the VPS market is a bit more commoditized and there are some other great options out there. Linode initially came to mind, but their future became a bit murkier after they got acquired by Akamai in 2022, while hyperscalers like AWS and Azure are too expensive for this use-case. I eventually landed on [Hetzner Cloud](https://www.hetzner.com/cloud) for the following reasons:
|
||||
|
||||
- Incredible value - for roughly $5 USD per month you get 2 vCPUs and 2GB of ram with 20TB of monthly traffic. That's basically double the specs of competing offerings.
|
||||
- Great reputation - Hetzner has been around for 20+ years and has lots of goodwill in the tech community for their frugal dedicated server offerings. I wouldn't have chose them initially since their Cloud product didn't have offerings in the U.S., but recently they've expanded to include VPSs in Virginia and Oregon.
|
||||
- Full-featured Terraform provider - This isn't unique to Hetzner, but it was a requirement for my new setup and their provider works great.
|
||||
|
||||
### Why not self host?
|
||||
|
||||
While I have a reliable server at home and 300mbps uploads, it's never going to match the bandwidth and reach of a regional data center. This wouldn't matter to me for most things, but I treat my Nextcloud server as a full Dropbox replacement, and it needs to perform as such. On that same note, I feel comfort knowing that it's separated from the more experimental environment of my homelab.
|
||||
|
||||
# Linux Distribution
|
||||
|
||||
One of the great benefits of containerized applications is that the host operating system matters much less than it used to, and the choice mostly comes down to personal preference. As long as it can run your chosen container runtime and you're familiar with the tooling, your choice will probably work as well as any other.
|
||||
|
||||
I've been running Ubuntu on my servers for years due to ease-of-use and my familiarity with it on the desktop. However, I've recently been using Fedora on my home computers and have gotten accustomed to Red Hat / RPM quirks and tooling in recent years. For this reason, and the ease of getting the latest Podman release (more below), I ended up choosing [CentOS Stream 9](https://www.centos.org/centos-stream/).
|
||||
|
||||
# Docker vs. Podman
|
||||
|
||||
I've been using [Docker](https://www.docker.com/) to host a number of applications on my home server for the last few years with great success, and Docker is still far-and-away the most popular way to run individual containers. However, as the [OCI standard](https://opencontainers.org/) has become more widely adopted, other tools like [Podman](https://podman.io/) have started to appear. Podman, backed by Red Hat, offers near 1:1 command compatibility with Docker and has some lovely added benefits such as:
|
||||
- Designed to run without root - Podman runs containers as a standard user, greatly reducing the risk to the server if one of the containers is compromised.
|
||||
- No daemon required - On the same note, there isn't a continuously running daemon in the background with root access to your system. The risks of the Docker socket are [well-documented](https://docs.docker.com/engine/security/protect-access/), and this negates that risk entirely.
|
||||
- Modern and lightweight - One of the benefits of not being first is that you can learn from everyone else's mistakes. Podman is built using lessons learned from Docker while creating an easy pathway to move from individual containers to full Kubernetes deployments.
|
||||
|
||||
Podman has been under rapid development recently, and there's a lot of excitement about it in Linux circles. While Docker would have worked just fine for my purposes, I decided to use this project as an opportunity to get familiar with Podman and see if it could potentially replace my other Docker-based applications.
|
||||
|
||||
# Deployment
|
||||
|
||||
Unlike my previous Nextcloud server which was like a zen garden that I tended carefully, I wanted my new server to be completely reproducible on a moment's notice. Using containers accomplishes part of this approach, but still leaves many parts of the server configuration to automate! Thankfully, there are a ton of tools available in 2023 to help with this.
|
||||
|
||||
## Terraform
|
||||
|
||||
To deploy the server itself, with associated volumes, firewall, etc, [Terraform](https://www.terraform.io/) was the obvious choice. While there are some competitors coming up like [Pulumi](https://www.pulumi.com/), Terraform is still the dominant player in the field and popularized the infrastructure-as-code concept. I had some experience using it at work, but I had never had the opportunity to build something from scratch with it. After reading the documentation for the [Hetzner Cloud provider](https://registry.terraform.io/providers/hetznercloud/hcloud/latest/docs), I was confident Terraform would be able to give me everything I needed.
|
||||
|
||||
## Ansible
|
||||
|
||||
Once the VPS is deployed and I have SSH access, Terraform's job stops. This is where I would typically connect to the server and start installing packages, configuring the webserver, and doing all the other server setup tasks I've done a thousand times over the years. If only there was a tool that could do all these steps for me while simultaneously documenting the entire setup!
|
||||
|
||||
Enter [Ansible](https://www.ansible.com/). Anything you could possibly think to do on a Linux box, Ansible can do for you. Think of it like a human-readable Bash script that handles all the rough edges for you. While writing the playbooks takes some work, once you have them written, you can run them again and again and expect (mostly) the same results each time. I chose Ansible due to it's stateless, agent-less architecture and the ability to run it from any computer with SSH access to the target hosts. Like Terraform, I love that the entire configuration is text-based and easily managed with Git.
|
||||
|
||||
# What's next?
|
||||
|
||||
This post talked about the ideas and goals I had going into this project, and in Part 2 I'll talk about the details of the implementation, and how sometimes things seem a lot easier in a blog post than they turn out to be in reality! If you're interested in the nitty-gritty of how these tools work for a project like this, stay tuned for the next post in the series.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
347
_posts/2023-08-28-nextcloud-podman-part2.md
Normal file
347
_posts/2023-08-28-nextcloud-podman-part2.md
Normal file
@@ -0,0 +1,347 @@
|
||||
---
|
||||
layout: single
|
||||
title: "Building a Reproducible Nextcloud Server, Part two: Setting up Podman containers"
|
||||
date: 2023-08-28 10:00:00
|
||||
excerpt: "In the second installment of my Nextcloud server rebuild, we'll get our containers up-and-running with Podman."
|
||||
categories: [Self-Hosting, Linux Administration]
|
||||
tags: linux nextcloud podman docker container vps
|
||||
comments: true
|
||||
---
|
||||
|
||||
[*Link to Part one*]({% link _posts/2023-08-27-nextcloud-podman.md %})
|
||||
|
||||
Now that I've established the stack, let's dive right in to setting up the Nextcloud application with Podman. By the end of this post, we'll have Nextcloud conatiners running locally along with systemd service files to reproduce them on any system.
|
||||
|
||||
## Notes on rootless Podman
|
||||
|
||||
One of the big advantages of using Podman over Docker is that Podman was designed from the beginning to run without root privileges. This has many positive security implications, but there also a number of "gotchas" to be aware of, and I'll be pointing them out as I go through the instructions.
|
||||
|
||||
For more details, the Podman project maintains a helpful doc on their Github: [The Shortcomings of Rootless Podman](https://github.com/containers/podman/blob/main/rootless.md).
|
||||
|
||||
## Create a pod
|
||||
|
||||
Podman "pods" are logical groupings of containers that depend on one another. Think of a pod like a Service in Docker Compose; a group of containers that work together to run a single application or service. Once we have a pod that contains all our containers, we can stop and start all of them with a single command. For a much more thorough explanation on what pods are and how they work, check out this [excellent post](https://developers.redhat.com/blog/2019/01/15/podman-managing-containers-pods) on the Red Hat developer blog.
|
||||
|
||||
**Rootless Gotcha #1**
|
||||
In most Linux distributions, unprivileged applications are not allowed to bind themselves to ports below 1024. To fix:
|
||||
1. Run `sudo sysctl net.ipv4.ip_unprivileged_port_start=80`
|
||||
2. Create a file under `/etc/sysctl.d/` and add the line `net.ipv4.ip_unprivileged_port_start=80`. This makes the change permanent.
|
||||
|
||||
Now, create a new pod called "nextcloud".
|
||||
|
||||
``` shell
|
||||
podman pod create \
|
||||
--publish 80:80 \
|
||||
--publish 443:443 \
|
||||
--network slirp4netns:port_handler=slirp4netns \
|
||||
nextcloud
|
||||
```
|
||||
|
||||
You can see your newly created pod by running `podman pod ps`.
|
||||
|
||||
``` shell
|
||||
POD ID NAME STATUS CREATED INFRA ID # OF CONTAINERS
|
||||
d1b78054d6f4 nextcloud Created 2 minutes ago f4a80daae64f 1
|
||||
```
|
||||
|
||||
#### Options explained
|
||||
* `--publish 80:80` and `--publish 443:443` opens ports 80 and 443 for the webserver. Containers within pods can communicate with eachother fully on their own isolated network, but for outside traffic to reach the containers, we need to open the necessary ports at the pod level.
|
||||
* `--network slirp4netns:port_handler=slirp4netns` solves another rootless gotcha. By default, the webserver in rootless mode sees all HTTP requests as coming from the container's local IP address. This isn't very helpful for accurate logs, so the above option changes the pod's port handler to fix the issue. There may be some performance penalties for doing this, but for low-traffic servers it shouldn't be a problem.
|
||||
|
||||
## Create the containers
|
||||
|
||||
To get Nextcloud up and running, we'll use the following containers:
|
||||
|
||||
* nextcoud-fpm - A minimal install of Nextcloud that requires a separate webserver.
|
||||
* mariadb - Database officially supported by Nextcloud.
|
||||
* caddy - The Caddy webserver, which I love for the simplicity of its config and the built-in automatic SSL via Let's Encrypt.
|
||||
|
||||
First, create a working directory structure where you'll store all the containers' data. For this project, I broke mine out like this:
|
||||
|
||||
``` shell
|
||||
.podman
|
||||
└── nextcloud
|
||||
├── caddy
|
||||
│ ├── config
|
||||
│ └── data
|
||||
├── mariadb
|
||||
└── nextcloud
|
||||
├── config
|
||||
└── data
|
||||
```
|
||||
|
||||
Next, I'll go over each container, showing you the full command I used to create them and explaining each option.
|
||||
|
||||
### MariaDB
|
||||
|
||||
We'll create the database container first since it doesn't technically depend on either of the other containers.
|
||||
|
||||
``` shell
|
||||
podman run \
|
||||
--detach \
|
||||
--env MYSQL_DATABASE=nextcloud \
|
||||
--env MYSQL_USER=nextcloud \
|
||||
--env MYSQL_PASSWORD=nextcloud \
|
||||
--env MYSQL_ROOT_PASSWORD=nextcloud \
|
||||
--volume $HOME/.podman/nextcloud/mariadb:/var/lib/mysql:z \
|
||||
--name mariadb \
|
||||
--pod nextcloud \
|
||||
docker.io/library/mariadb:10
|
||||
```
|
||||
|
||||
#### Options explained
|
||||
|
||||
* `--env MYSQL_DATABASE=nextcloud` - Name of the database Nextcloud will use.
|
||||
* `--env MYSQL_USER=nextcloud` - Database user Nextcloud will use.
|
||||
* `--env MYSQL_PASSWORD=nextcloud` - Password for the Nextcloud database user. Be sure to change this to something more secure and save it somewhere!
|
||||
* `--env MYSQL_ROOT_PASSWORD=nextcloud` - Password for the extcloud database root user. Be sure to change this to something more secure and save it somewhere!
|
||||
* `--volume $HOME/.podman/nextcloud/mariadb:/var/lib/mysql:z` - Creates a bind mount in the folder you created for MariaDB to store its database and configuration data. The `:z` option is needed to give directory access on selinux systems.
|
||||
* `--name mariadb` - Sets the name of the container.
|
||||
* `--pod nextcloud` - Attaches the container to the nextcloud pod we previously created.
|
||||
* `docker.io/library/mariadb:10` - Container image we're going to download and run.
|
||||
|
||||
After you run the command, you can check if the container is running with the `podman ps` command.
|
||||
|
||||
``` shell
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
f4a80daae64f localhost/podman-pause:4.7.0-1695839078 About an hour ago Up 29 seconds 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp d1b78054d6f4-infra
|
||||
c5961a86a474 docker.io/library/mariadb:10 mariadbd 29 seconds ago Up 29 seconds 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp mariadb
|
||||
```
|
||||
|
||||
**Note:** The other container you see in the output, `d1b78054d6f4-infra` is a helper container for the nextcloud pod.
|
||||
|
||||
### Nextcloud
|
||||
|
||||
``` shell
|
||||
podman run \
|
||||
--detach \
|
||||
--env MYSQL_HOST=mariadb \
|
||||
--env MYSQL_DATABASE=nextcloud \
|
||||
--env MYSQL_USER=nextcloud \
|
||||
--env MYSQL_PASSWORD=nextcloud \
|
||||
--volume $HOME/.podman/nextcloud/nextcloud/config:/var/www/html:z \
|
||||
--volume $HOME/.podman/nextcloud/nextcloud/data:/var/www/html/data:z \
|
||||
--name nextcloud-app \
|
||||
--pod nextcloud \
|
||||
docker.io/library/nextcloud:27-fpm
|
||||
```
|
||||
|
||||
#### Options explained
|
||||
|
||||
* `--env MYSQL_HOST=mariadb` - Name of the container hosting the database. Thanks to Podman's built-in DNS, container names will resolve to their IP address, so all we have to do is point Nextcloud at `mariadb` and it will find the database.
|
||||
* `--env MYSQL_DATABASE=nextcloud` - Name of the database Nextcloud will use, the same that you created in the `mariadb` container.
|
||||
* `--env MYSQL_USER=nextcloud` - Database user Nextcloud will use, the same that you created in the `mariadb` container.
|
||||
* `--env MYSQL_PASSWORD=nextcloud` - Password for the Nextcloud database user, the same that you created in the `mariadb` container.
|
||||
* `--volume $HOME/.podman/nextcloud/nextcloud/config:/var/www/html:z` - Creates a bind mount in the folder you created for Nextcloud to store its configuration files. The `:z` option is needed to give directory access on selinux systems.
|
||||
* `--volume $HOME/.podman/nextcloud/nextcloud/data:/var/www/html/data:z` - Creates a bind mount in the folder you created for Nextcloud's data directory. The `:z` option is needed to give directory access on selinux systems.
|
||||
* `--name nextcloud-app` - Sets the name of the container.
|
||||
* `--pod nextcloud` - Attaches the container to the nextcloud pod we previously created.
|
||||
* `docker.io/library/mariadb:10` - Container image we're going to download and run.
|
||||
|
||||
You should now have both containers running:
|
||||
|
||||
``` shell
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
f4a80daae64f localhost/podman-pause:4.7.0-1695839078 About an hour ago Up 18 minutes 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp d1b78054d6f4-infra
|
||||
c5961a86a474 docker.io/library/mariadb:10 mariadbd 18 minutes ago Up 18 minutes 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp mariadb
|
||||
13d5c43c0b4d docker.io/library/nextcloud:27-fpm php-fpm 5 seconds ago Up 5 seconds 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp nextcloud-app
|
||||
```
|
||||
|
||||
### Caddy
|
||||
|
||||
Before we start the Caddy container, we'll need to write a config in the form of a Caddyfile. Since we're just focused on getting the initial containers working, let's do a simple configuration without HTTPS:
|
||||
|
||||
Create file named `Caddyfile` in `$HOME/.podman/nextcloud/caddy/config/` and paste the below contents.
|
||||
|
||||
``` hcl
|
||||
http://localhost:80 {
|
||||
|
||||
root * /var/www/html
|
||||
file_server
|
||||
php_fastcgi nextcloud-app:9000 {
|
||||
root /var/www/html
|
||||
env front_controller_active true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The above configuration is a bare-minimum to run Nextcloud locally on port 80. We'll make lots of tweaks before we're ready for production.
|
||||
|
||||
Assuming the Caddyfile is in place, run the below command to spin up the final container:
|
||||
|
||||
``` shell
|
||||
podman run \
|
||||
--detach \
|
||||
--volume $HOME/.podman/nextcloud/nextcloud/config:/var/www/html:z \
|
||||
--volume $HOME/.podman/nextcloud/caddy/config/Caddyfile:/etc/caddy/Caddyfile:z \
|
||||
--volume $HOME/.podman/nextcloud/caddy/data:/data:z \
|
||||
--name caddy \
|
||||
--pod nextcloud \
|
||||
docker.io/library/caddy
|
||||
```
|
||||
|
||||
#### Options explained
|
||||
|
||||
* `--volume $HOME/.podman/nextcloud/nextcloud/config:/var/www/html:z` - Creates a bind mount in the folder you created for Nextcloud to store its configuration files. This is the content Caddy serves to the web, so it needs access.
|
||||
* `--volume $HOME/.podman/nextcloud/caddy/config/Caddyfile:/etc/caddy/Caddyfile:z` - Creates a bind mount for the CaddyFile.
|
||||
* `--volume $HOME/.podman/nextcloud/caddy/data:/data:z` - Creates a bind mount for Caddy's data folder.
|
||||
* `--name caddy` - Sets the name of the container.
|
||||
* `--pod nextcloud` - Attaches the container to the nextcloud pod we previously created.
|
||||
* `docker.io/library/caddy` - Container image we're going to download and run.
|
||||
|
||||
Verify that all (3) containers are running with `podman ps`.
|
||||
|
||||
``` shell
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
f4a80daae64f localhost/podman-pause:4.7.0-1695839078 2 hours ago Up 45 minutes 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp d1b78054d6f4-infra
|
||||
c5961a86a474 docker.io/library/mariadb:10 mariadbd 45 minutes ago Up 45 minutes 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp mariadb
|
||||
13d5c43c0b4d docker.io/library/nextcloud:27-fpm php-fpm 26 minutes ago Up 26 minutes 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp nextcloud-app
|
||||
b29486a99286 docker.io/library/caddy:latest caddy run --confi... 4 minutes ago Up 4 minutes 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp caddy
|
||||
```
|
||||
\
|
||||
Go to http://localhost in your browser and...
|
||||
|
||||
{:class="img-responsive"}
|
||||
|
||||
Ta-da! We have Nextcloud!
|
||||
|
||||
Since the containers are all part of the `nextcloud` pod, you can stop and start all of them with one command. You can run `podman pod stop` to take them down and `podman pod start` to bring them back up. Pretty cool eh?
|
||||
|
||||
## Generate Systemd files
|
||||
|
||||
Even better than starting/stopping your containers at the pod level is doing it with systemd! This will allow you to manage your nextcloud pod the same way as any other systemd service, including enabling it to run at system start.
|
||||
|
||||
Instead of writing all the systemd unit files by hand, we're going to use a handy subcommand of the podman application, `podman generate systemd`.
|
||||
|
||||
First, make sure the pod and all its containers are running. Then, run the below command:
|
||||
|
||||
``` shell
|
||||
podman generate systemd --new --files --name nextcloud
|
||||
|
||||
/home/raylyon/container-nextcloud-app.service
|
||||
/home/raylyon/container-caddy.service
|
||||
/home/raylyon/container-mariadb.service
|
||||
/home/raylyon/pod-nextcloud.service
|
||||
```
|
||||
|
||||
The output gives you the path to each file, and we'll need to move these files into the systemd user directory, `$HOME/.local/share/systemd/user/` Create the directory if it doesn't already exist.
|
||||
|
||||
``` shell
|
||||
mkdir -p $HOME/.config/systemd/user
|
||||
```
|
||||
|
||||
Copy each of the files into the above directory.
|
||||
|
||||
``` shell
|
||||
cp $HOME/*.service $HOME/.config/systemd/user/
|
||||
```
|
||||
|
||||
Reload the systemd user daemon.
|
||||
|
||||
``` shell
|
||||
systemctl --user daemon-reload
|
||||
```
|
||||
|
||||
Start the service corresponding to the pod.
|
||||
|
||||
``` shell
|
||||
systemctl --user start pod-nextcloud
|
||||
```
|
||||
|
||||
`podman ps` should show that all your containers are running. If you have issues, you can troubleshoot the same way you would for another systemd service.
|
||||
|
||||
Check the status of the pod.
|
||||
|
||||
``` shell
|
||||
systemctl --user status pod-nextcloud
|
||||
```
|
||||
|
||||
Check the status of an individual container.
|
||||
|
||||
``` shell
|
||||
systemctl --user status container-nextcloud-app
|
||||
```
|
||||
|
||||
Check the service output for errors (note that you need `sudo` for this one).
|
||||
|
||||
``` shell
|
||||
sudo journalctl -xe
|
||||
```
|
||||
|
||||
## Moving to production
|
||||
|
||||
Up until now we've been working with our containers on localhost, but now it's time to move them to a public facing server with a FQDN and public IP. This step in the process highlights one of the biggest selling points of containers; we can develop and configure locally, then push that exact working configuration to another server and it Just Works™. Beyond that, our systemd unit files save us the trouble of remembering the exact `podman` commands to run on the server, so we can simply copy the files and start the service.
|
||||
|
||||
To begin, let's do just that. Copy the `*.service` files from your computer to the public-facing server with a tool like `scp` or `rsync`.
|
||||
|
||||
``` shell
|
||||
scp $HOME/.config/systemd/user/*.service user@your.server.com:/home/user/
|
||||
```
|
||||
|
||||
Then, on the **production server** recreate the folder structure you used locally.
|
||||
|
||||
``` shell
|
||||
mkdir -p $HOME/.podman/nextcloud/nextcloud/config
|
||||
mkdir -p $HOME/.podman/nextcloud/nextcloud/data
|
||||
mkdir -p $HOME/.podman/nextcloud/caddy/config
|
||||
mkdir -p $HOME/.podman/nextcloud/caddy/data
|
||||
mkdir -p $HOME/.podman/nextcloud/mariadb
|
||||
```
|
||||
|
||||
Also the systemd folder in case it's not there.
|
||||
|
||||
``` shell
|
||||
mkdir -p $HOME/.config/systemd/user
|
||||
```
|
||||
|
||||
Copy the service files into the systemd user directory and reload systemd.
|
||||
|
||||
``` shell
|
||||
cp $HOME/*.service $HOME/.config/systemd/user/
|
||||
systemctl --user daemon-reload
|
||||
```
|
||||
|
||||
### Caddyfile
|
||||
|
||||
The Caddyfile we used earlier won't be suitable for production since it doesn't use an FQDN or HTTP(s). Create a new Caddyfile on the server in `$HOME/.podman/nextcloud/caddy/config/` with the below contents, replacing the domain with one you've set up for the server.
|
||||
|
||||
``` hcl
|
||||
your.server.com {
|
||||
|
||||
root * /var/www/html
|
||||
file_server
|
||||
php_fastcgi nextcloud-app:9000 {
|
||||
root /var/www/html
|
||||
env front_controller_active true
|
||||
}
|
||||
|
||||
encode gzip
|
||||
|
||||
log {
|
||||
output file /data/nextcloud-access.log
|
||||
}
|
||||
|
||||
header {
|
||||
Strict-Transport-Security "max-age=15768000;includeSubDomains;preload"
|
||||
}
|
||||
|
||||
# .htaccess / data / config / ... shouldn't be accessible from outside
|
||||
@forbidden {
|
||||
path /.htaccess
|
||||
path /data/*
|
||||
path /config/*
|
||||
path /db_structure
|
||||
path /.xml
|
||||
path /README
|
||||
path /3rdparty/*
|
||||
path /lib/*
|
||||
path /templates/*
|
||||
path /occ
|
||||
path /console.php
|
||||
}
|
||||
respond @forbidden 404
|
||||
|
||||
redir /.well-known/carddav /remote.php/dav 301
|
||||
redir /.well-known/caldav /remote.php/dav 301
|
||||
}
|
||||
```
|
||||
BIN
assets/images/screenshots/nextcloud-podman01.png
Normal file
BIN
assets/images/screenshots/nextcloud-podman01.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 471 KiB |
Reference in New Issue
Block a user