Skip to content

Commit

Permalink
Merge pull request #395 from Trim/configurable-public-port
Browse files Browse the repository at this point in the history
allow to use custom HTTP public port to permit rootless run
  • Loading branch information
Trim authored Sep 22, 2024
2 parents a0085c9 + 08d1dd3 commit f9f0de0
Show file tree
Hide file tree
Showing 25 changed files with 116 additions and 69 deletions.
69 changes: 30 additions & 39 deletions Container.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,60 +5,53 @@ To simplify set up of a development environment, LinuxFr.org can be
run with a container engine like Docker or Podman with the [`compose.yml`](./compose.yaml)
file which describes how to build all needed services.

If you use the Docker engine, you can use the `docker compose up` command to start the system (you
need to install the [Docker compose plugin](https://docs.docker.com/compose/)).
By default, the LinuxFr.org services will be provided under the domain names
`dlfp.lo` and `image.dlfp.lo`. So you'll need to add the
following line into the `/etc/hosts` file of your machine:

```
127.0.0.1 dlfp.lo image.dlfp.lo
```

Then, if you use the Docker engine, you can use the `docker compose up`
command to start the system (you need to install the
[Docker compose plugin](https://docs.docker.com/compose/) first).

> Note: with the Docker engine, you need to enable the Docker BuildKit builder.
> Either you have a Docker version which uses it by default, or you set the
> environment variable `export DOCKER_BUILDKIT=1`.
If you use Podman, you can either use the same Docker compose plugin or the
[podman-compose](https://github.com/containers/podman-compose/)
utility. The podman cli itself provide a wrapper of one of these two tools through the
If you use the Podman engine, you can either use the same Docker compose plugin
or the [podman-compose](https://github.com/containers/podman-compose/)
tool. The podman cli itself provides a wrapper of one of these two tools
through the
[`podman compose` command](https://docs.podman.io/en/latest/markdown/podman-compose.1.html).
Thus you need to use the `podman compose up` command to start the system.

At this point, the documentation will give you `docker compose` commands, but you should be able
to use `podman compose` without any issue.
At this point, this documentation will give you `docker compose` commands,
but you should be able to use `podman compose` without any issue.

To init the SQL database schema, you need to wait up to the `database`
container to be ready to listen MySQL connections.
To setup the SQL database schema, you need to wait until the `database`
container becomes ready to listen MySQL connections.

For example, you should see in the logs:

> database_1 | 2020-09-21 16:03:12 139820938893312 [Note] mysqld: ready for connections.
> database_1 | 2020-09-21 16:03:12 139820938893312 [Note] *mysqld: ready for connections.*
>
> database_1 | Version: '10.1.46-MariaDB-1\~bionic' socket: '/var/run/mysqld/mysqld.sock' port: 3306 mariadb.org binary distribution
Or you can check the `database` container status to be "healthy".
Or you can check the `database` container status to be *healthy* with the
`docker compose ps` command.

Then, open a second terminal and run:

```
docker compose exec linuxfr.org bin/rails db:setup
```

Finally, the environment is ready and you can open [http://dlfp.lo](http://dlfp.lo)
Finally, the environment is ready and you can open [http://dlfp.lo:9000](http://dlfp.lo:9000)
in your favorite browser.

Notes:

1. to be able to access this URL, you'll need to add the following line
into the `/etc/hosts` file of your machine:

```
127.0.0.1 dlfp.lo image.dlfp.lo
```

2. for [rootless containers](https://rootlesscontaine.rs/), you'll need
to allow standard users to listen on ports less than 1024
(this is needed because linuxfr use port 80 and 443):

```sh
sudo sysctl net.ipv4.ip_unprivileged_port_start=80
```


Personalize configuration
=========================

Expand All @@ -68,16 +61,14 @@ If you want, you can change the domain names used by the LinuxFr.org
web application. To do this, you can setup `DOMAIN` and `IMAGE_DOMAIN`
variables in the `deployment/default.env` file.

You can also configure your own Redis service and your own MySQL
service.
If you want to change the application port and/or other configurations, you can
[override](https://docs.docker.com/compose/extends/)
the docker compose configuration (in particular the `nginx` service for
the port).
Within the same file, you can update the HTTP listening ports by updating the
`DOMAIN_HTTP_PORT` and `IMAGE_DOMAIN_HTTP_PORT` variables (both are set to
`9000` by default). If you modify them, don't forget to add the new values as
published ports for the `nginx` service in the `compose.yaml` file (they have
to target the `8080` container port).

Notice, that if LinuxFr.org doesn't run on port 80, the image cache
service won't work well and so you won't be able to see images in the news.
You can also configure your own Redis service and your own MySQL
service by updating environment variables in the same file.

Test modifications
==================
Expand Down
17 changes: 13 additions & 4 deletions INSTALL.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,11 +131,20 @@ Additionally, you run the boards within another terminal:

This extra step isn't really needed to be able to use LinuxFr.org.

In the `config/environments/development.rb` file, there are two domains set
inside variables `MY_DOMAIN` and `IMG_DOMAIN`.
By default both domains are `dlfp.lo`.
In the `config/environments/development.rb` file, there are these variables:

You'll find this domain inside some documents like emails to confirm user
1. `MY_DOMAIN` and `IMG_DOMAIN` which define the domain name for the LinuxFr
service and the image caching service.
By default both domain names are `dlfp.lo`.

2. `MY_PUBLIC_URL` and `IMG_PUBLIC_PORT` which define the public HTTP port for
both services.
By default both ports are `80`.

These two set of variables are used to build the public url of the two
services. By default both public urls are `http://dlfp.lo`.

You'll find this public url inside some documents like emails to confirm user
subscription. To simplify your usage of LinuxFr.org, you should consider
install a website locally using this domain name.

Expand Down
2 changes: 1 addition & 1 deletion app/controllers/admin/stylesheets_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ def show

def create
Stylesheet.temporary(current_account, params[:url]) do
redirect_to "/" + Stylesheet.capture("http://#{MY_DOMAIN}/", cookies)
redirect_to "/" + Stylesheet.capture("#{MY_PUBLIC_URL}/", cookies)
end
end

Expand Down
2 changes: 1 addition & 1 deletion app/helpers/atom_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ def atom_comments_link(content, url)
str = <<-EOS
<p>
<strong>Commentaires :</strong>
<a href=\"//#{MY_DOMAIN}/nodes/#{content.node.id}/comments.atom\">voir le flux Atom</a>
<a href=\"#{MY_PUBLIC_URL}/nodes/#{content.node.id}/comments.atom\">voir le flux Atom</a>
<a href=\"#{url}#comments\">ouvrir dans le navigateur</a>
</p>
EOS
Expand Down
2 changes: 1 addition & 1 deletion app/models/diary.rb
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ def convert
@news.save!
$redis.set "convert/#{@news.id}", self.id
@news.node.update_column(:cc_licensed, node.cc_licensed)
@news.links.create title: "Journal à l’origine de la dépêche", url: "https://#{MY_DOMAIN}/users/#{owner.to_param}/journaux/#{to_param}", lang: "fr"
@news.links.create title: "Journal à l’origine de la dépêche", url: "#{MY_PUBLIC_URL}/users/#{owner.to_param}/journaux/#{to_param}", lang: "fr"
@news
end
end
Expand Down
2 changes: 1 addition & 1 deletion app/models/image.rb
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ def src(type="img")
return link if internal_link?
return E403 if blacklisted?
register_in_redis
"//#{IMG_DOMAIN}/#{type}/#{encoded_link}/#{filename}"
"#{IMG_PUBLIC_URL}/#{type}/#{encoded_link}/#{filename}"
end

def src_attr
Expand Down
2 changes: 1 addition & 1 deletion app/models/node.rb
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ def set_taglist(list, user_id)
if tag.new_record?
tag.save!
user = User.find(user_id)
Board.amr_notification("L’étiquette #{tagname} https://#{MY_DOMAIN}/tags/#{tagname}/public vient d’être créée par #{user.name} https://#{MY_DOMAIN}/users/#{user.cached_slug}")
Board.amr_notification("L’étiquette #{tagname} #{MY_PUBLIC_URL}/tags/#{tagname}/public vient d’être créée par #{user.name} #{MY_PUBLIC_URL}/users/#{user.cached_slug}")
end
taggings.create(tag_id: tag.id, user_id: user_id)
end
Expand Down
4 changes: 2 additions & 2 deletions app/uploaders/avatar_uploader.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
class AvatarUploader < CarrierWave::Uploader::Base

AVATAR_SIZE = 64
DEFAULT_AVATAR_URL = "//#{MY_DOMAIN}/images/default-avatar.svg"
DEFAULT_AVATAR_URL = "#{MY_PUBLIC_URL}/images/default-avatar.svg"

include CarrierWave::MiniMagick
process resize_and_pad: [AVATAR_SIZE, AVATAR_SIZE]
Expand All @@ -13,7 +13,7 @@ def base_dir
end

def url
super.sub(base_dir.to_s, "//#{IMG_DOMAIN}")
super.sub(base_dir.to_s, "#{IMG_PUBLIC_URL}")
end

def store_dir
Expand Down
2 changes: 1 addition & 1 deletion app/uploaders/stylesheet_uploader.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ def base_dir
end

def url
super.sub(base_dir.to_s, "//#{IMG_DOMAIN}")
super.sub(base_dir.to_s, "#{IMG_PUBLIC_URL}")
end

def store_dir
Expand Down
2 changes: 1 addition & 1 deletion app/views/bookmarks/_bookmark.atom.builder
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@ feed.entry(bookmark, :url => url) do |entry|
bookmark.node.popular_tags.each do |tag|
entry.category(:term => tag.name)
end
entry.wfw :commentRss, "https://#{MY_DOMAIN}/nodes/#{bookmark.node.id}/comments.atom"
entry.wfw :commentRss, "#{MY_PUBLIC_URL}/nodes/#{bookmark.node.id}/comments.atom"
end
2 changes: 1 addition & 1 deletion app/views/diaries/_diary.atom.builder
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@ feed.entry(diary, :url => url) do |entry|
diary.node.popular_tags.each do |tag|
entry.category(:term => tag.name)
end
entry.wfw :commentRss, "https://#{MY_DOMAIN}/nodes/#{diary.node.id}/comments.atom"
entry.wfw :commentRss, "#{MY_PUBLIC_URL}/nodes/#{diary.node.id}/comments.atom"
end
4 changes: 2 additions & 2 deletions app/views/news/_news.atom.builder
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ feed.entry(news, :published => news.node.created_at) do |entry|
first = content_tag(:div, news.body)
links = content_tag(:ul, news.links.map.with_index do |l,i|
content_tag(:li, "lien nᵒ #{i+1} : ".html_safe +
link_to(l.title, "https://#{MY_DOMAIN}/redirect/#{l.id}", :title => l.url, :hreflang => l.lang))
link_to(l.title, "#{MY_PUBLIC_URL}/redirect/#{l.id}", :title => l.url, :hreflang => l.lang))
end.join.html_safe)
second = content_tag(:div, news.second_part)
if news.published?
Expand All @@ -32,6 +32,6 @@ feed.entry(news, :published => news.node.created_at) do |entry|
entry.category(:term => tag.name)
end
if news.published?
entry.wfw :commentRss, "https://#{MY_DOMAIN}/nodes/#{news.node.id}/comments.atom"
entry.wfw :commentRss, "#{MY_PUBLIC_URL}/nodes/#{news.node.id}/comments.atom"
end
end
2 changes: 1 addition & 1 deletion app/views/polls/_poll.atom.builder
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ feed.entry(poll, :published => poll.node.created_at) do |entry|
poll.node.popular_tags.each do |tag|
entry.category(:term => tag.name)
end
entry.wfw :commentRss, "https://#{MY_DOMAIN}/nodes/#{poll.node.id}/comments.atom"
entry.wfw :commentRss, "#{MY_PUBLIC_URL}/nodes/#{poll.node.id}/comments.atom"
end
2 changes: 1 addition & 1 deletion app/views/posts/_post.atom.builder
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@ feed.entry(post, :url => url) do |entry|
post.node.popular_tags.each do |tag|
entry.category(:term => tag.name)
end
entry.wfw :commentRss, "https://#{MY_DOMAIN}/nodes/#{post.node.id}/comments.atom"
entry.wfw :commentRss, "#{MY_PUBLIC_URL}/nodes/#{post.node.id}/comments.atom"
end
2 changes: 1 addition & 1 deletion app/views/stylesheets/edit.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
Pour cela, il vous suffit de commencer votre feuille de style par la déclaration suivante :

%pre
@import url("//#{MY_DOMAIN}/assets/application.css");
@import url("#{MY_PUBLIC_URL}/assets/application.css");

%div.sideforms
= form_tag "/stylesheet", method: :put do
Expand Down
2 changes: 1 addition & 1 deletion app/views/trackers/_tracker.atom.builder
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@ feed.entry(tracker) do |entry|
tracker.node.popular_tags.each do |tag|
entry.category(:term => tag.name)
end
entry.wfw :commentRss, "https://#{MY_DOMAIN}/nodes/#{tracker.node.id}/comments.atom"
entry.wfw :commentRss, "#{MY_PUBLIC_URL}/nodes/#{tracker.node.id}/comments.atom"
end
2 changes: 1 addition & 1 deletion app/views/wiki_pages/_wiki_page.atom.builder
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ feed.entry(wiki_page) do |entry|
wiki_page.node.popular_tags.each do |tag|
entry.category(:term => tag.name)
end
entry.wfw :commentRss, "https://#{MY_DOMAIN}/nodes/#{wiki_page.node.id}/comments.atom"
entry.wfw :commentRss, "#{MY_PUBLIC_URL}/nodes/#{wiki_page.node.id}/comments.atom"
end
11 changes: 7 additions & 4 deletions compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -62,19 +62,22 @@ services:
- cache-img:/linuxfr-img/cache

nginx:
image: docker.io/nginx:stable
image: docker.io/nginxinc/nginx-unprivileged:stable-alpine
env_file:
- deployment/default.env
volumes:
- ./deployment/nginx/templates:/etc/nginx/templates:Z
- ./public/fonts:/var/linuxfr/fonts:Z
- data-uploads:/var/linuxfr/uploads
ports:
- target: 80
published: 127.0.0.1:80
- target: 8080
# If you customize the published port, you have to update the
# DOMAIN_HTTP_PORT and IMAGE_DOMAIN_HTTP_PORT variables
# into the `deployment/default.env` file too
published: 127.0.0.1:9000
protocol: tcp
healthcheck:
test: ["CMD", "curl", "--silent", "--fail", "--fail-early", "--head", "http://$$DOMAIN", "http://$$DOMAIN/img", "http://$$DOMAIN/b", "http://$$IMAGE_DOMAIN/status"]
test: ["CMD", "curl", "--silent", "--fail", "--fail-early", "--location", "--head", "http://$$DOMAIN:8080", "http://$$DOMAIN:8080/img/status", "http://$$DOMAIN:8080/b", "http://$$IMAGE_DOMAIN:8080/status"]
interval: 10s
start_period: 5s
depends_on:
Expand Down
2 changes: 2 additions & 0 deletions config/environments/alpha.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
Rails.application.configure do
# Settings specified here will take precedence over those in config/application.rb.
MY_DOMAIN = 'alpha.linuxfr.org'
MY_PUBLIC_URL = 'https://alpha.linuxfr.org'
IMG_DOMAIN = 'img.alpha.linuxfr.org'
IMG_PUBLIC_URL = 'https://img.alpha.linuxfr.org'

# Code is not reloaded between requests.
config.cache_classes = true
Expand Down
26 changes: 26 additions & 0 deletions config/environments/development.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,35 @@
Rails.application.configure do
# Settings specified here will take precedence over those in config/application.rb.
MY_DOMAIN = ENV["DOMAIN"] || "dlfp.lo"
MY_PUBLIC_PORT = ENV["DOMAIN_HTTP_PORT"] || "80"

linuxfr_service_url = "http://#{MY_DOMAIN}"
if MY_PUBLIC_PORT != "" and MY_PUBLIC_PORT != "80"
linuxfr_service_url = "#{linuxfr_service_url}:#{ MY_PUBLIC_PORT}"
end

if MY_PUBLIC_PORT == "443"
linuxfr_service_url = "https://#{MY_DOMAIN}"
end
MY_PUBLIC_URL = linuxfr_service_url


IMG_DOMAIN = ENV["IMAGE_DOMAIN"] || "dlfp.lo"
IMG_PUBLIC_PORT = ENV["IMAGE_DOMAIN_HTTP_PORT"] || "80"

image_service_url = "http://#{IMG_DOMAIN}"
if IMG_PUBLIC_PORT != "" and IMG_PUBLIC_PORT != "80"
image_service_url = "#{image_service_url}:#{ IMG_PUBLIC_PORT}"
end

if IMG_PUBLIC_PORT == "443"
image_service_url = "https://#{IMG_DOMAIN}"
end
IMG_PUBLIC_URL = image_service_url


config.hosts << MY_DOMAIN
config.hosts << IMG_DOMAIN

# In the development environment your application's code is reloaded any time
# it changes. This slows down response time but is perfect for development
Expand Down
2 changes: 2 additions & 0 deletions config/environments/production.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
Rails.application.configure do
# Settings specified here will take precedence over those in config/application.rb.
MY_DOMAIN = "linuxfr.org"
MY_PUBLIC_URL = 'https://linuxfr.org'
IMG_DOMAIN = "img.linuxfr.org"
IMG_PUBLIC_URL = 'https://img.linuxfr.org'

# Code is not reloaded between requests.
config.enable_reloading = false
Expand Down
2 changes: 2 additions & 0 deletions config/environments/test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
Rails.application.configure do
# Settings specified here will take precedence over those in config/application.rb.
MY_DOMAIN = "dlfp.lo"
MY_PUBLIC_URL = "http://dlfp.lo:9000"
IMG_DOMAIN = "img.dlfp.lo"
IMG_PUBLIC_URL = "http://dlfp.lo:9000"

# While tests run files are not watched, reloading is not necessary.
config.enable_reloading = false
Expand Down
7 changes: 7 additions & 0 deletions deployment/default.env
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
# LinuxFr configuration
DOMAIN=dlfp.lo
# If you want to customize the public HTTP port, do not forget to add it to
# published ports of the `nginx` service into the `compose.yaml` file.
DOMAIN_HTTP_PORT=9000

IMAGE_DOMAIN=image.dlfp.lo
# If you want to customize the image public HTTP port, do not forget to add it to
# published ports of the `nginx` service into the `compose.yaml` file.
IMAGE_DOMAIN_HTTP_PORT=9000

# Redis service is used as a caching service and a publish/subscribe service
# to allow the different LinuxFr tools work together
Expand Down
Loading

0 comments on commit f9f0de0

Please sign in to comment.