diff --git a/Container.md b/Container.md index 140b0d750..7bae0b621 100644 --- a/Container.md +++ b/Container.md @@ -5,32 +5,43 @@ 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: @@ -38,27 +49,9 @@ 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 ========================= @@ -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 ================== diff --git a/INSTALL.md b/INSTALL.md index 30691a892..8445b23f8 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -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. diff --git a/app/controllers/admin/stylesheets_controller.rb b/app/controllers/admin/stylesheets_controller.rb index f5b94e200..07adf7f71 100644 --- a/app/controllers/admin/stylesheets_controller.rb +++ b/app/controllers/admin/stylesheets_controller.rb @@ -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 diff --git a/app/helpers/atom_helper.rb b/app/helpers/atom_helper.rb index 9a4e26e7f..f2a27a3a1 100644 --- a/app/helpers/atom_helper.rb +++ b/app/helpers/atom_helper.rb @@ -5,7 +5,7 @@ def atom_comments_link(content, url) str = <<-EOS
Commentaires : - voir le flux Atom + voir le flux Atom ouvrir dans le navigateur
EOS diff --git a/app/models/diary.rb b/app/models/diary.rb index aaaa4e585..fbe7f4845 100644 --- a/app/models/diary.rb +++ b/app/models/diary.rb @@ -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 diff --git a/app/models/image.rb b/app/models/image.rb index ffd826fe2..50be1a446 100644 --- a/app/models/image.rb +++ b/app/models/image.rb @@ -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 diff --git a/app/models/node.rb b/app/models/node.rb index 6fd64da5f..32fe96884 100644 --- a/app/models/node.rb +++ b/app/models/node.rb @@ -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 diff --git a/app/uploaders/avatar_uploader.rb b/app/uploaders/avatar_uploader.rb index 5d7228655..ab4532009 100644 --- a/app/uploaders/avatar_uploader.rb +++ b/app/uploaders/avatar_uploader.rb @@ -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] @@ -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 diff --git a/app/uploaders/stylesheet_uploader.rb b/app/uploaders/stylesheet_uploader.rb index 32fddaa9a..cdc372423 100644 --- a/app/uploaders/stylesheet_uploader.rb +++ b/app/uploaders/stylesheet_uploader.rb @@ -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 diff --git a/app/views/bookmarks/_bookmark.atom.builder b/app/views/bookmarks/_bookmark.atom.builder index 92f629804..31bacb8c2 100644 --- a/app/views/bookmarks/_bookmark.atom.builder +++ b/app/views/bookmarks/_bookmark.atom.builder @@ -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 diff --git a/app/views/diaries/_diary.atom.builder b/app/views/diaries/_diary.atom.builder index 6f9cf9149..d23660c03 100644 --- a/app/views/diaries/_diary.atom.builder +++ b/app/views/diaries/_diary.atom.builder @@ -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 diff --git a/app/views/news/_news.atom.builder b/app/views/news/_news.atom.builder index d0c66edd3..ea991d0da 100644 --- a/app/views/news/_news.atom.builder +++ b/app/views/news/_news.atom.builder @@ -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? @@ -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 diff --git a/app/views/polls/_poll.atom.builder b/app/views/polls/_poll.atom.builder index 852e2d6ce..c5e123cf1 100644 --- a/app/views/polls/_poll.atom.builder +++ b/app/views/polls/_poll.atom.builder @@ -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 diff --git a/app/views/posts/_post.atom.builder b/app/views/posts/_post.atom.builder index aa73c3487..606aac7e7 100644 --- a/app/views/posts/_post.atom.builder +++ b/app/views/posts/_post.atom.builder @@ -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 diff --git a/app/views/stylesheets/edit.html.haml b/app/views/stylesheets/edit.html.haml index 19fc17fe8..539c2a2d6 100644 --- a/app/views/stylesheets/edit.html.haml +++ b/app/views/stylesheets/edit.html.haml @@ -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 diff --git a/app/views/trackers/_tracker.atom.builder b/app/views/trackers/_tracker.atom.builder index deffa237b..479e1ab88 100644 --- a/app/views/trackers/_tracker.atom.builder +++ b/app/views/trackers/_tracker.atom.builder @@ -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 diff --git a/app/views/wiki_pages/_wiki_page.atom.builder b/app/views/wiki_pages/_wiki_page.atom.builder index 022a6e4ba..7cc4089a6 100644 --- a/app/views/wiki_pages/_wiki_page.atom.builder +++ b/app/views/wiki_pages/_wiki_page.atom.builder @@ -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 diff --git a/compose.yaml b/compose.yaml index c25df302b..e4da03f3b 100644 --- a/compose.yaml +++ b/compose.yaml @@ -62,7 +62,7 @@ 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: @@ -70,11 +70,14 @@ services: - ./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: diff --git a/config/environments/alpha.rb b/config/environments/alpha.rb index 9cd63bc52..5ade0f32c 100644 --- a/config/environments/alpha.rb +++ b/config/environments/alpha.rb @@ -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 diff --git a/config/environments/development.rb b/config/environments/development.rb index a4f3867f2..8b80e6575 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -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 diff --git a/config/environments/production.rb b/config/environments/production.rb index f70a9d1c5..17c477e43 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -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 diff --git a/config/environments/test.rb b/config/environments/test.rb index 526a40a31..c8d9216c0 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -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 diff --git a/deployment/default.env b/deployment/default.env index 5bd82e4fc..45106cb73 100644 --- a/deployment/default.env +++ b/deployment/default.env @@ -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 diff --git a/deployment/nginx/templates/dlfp.conf.template b/deployment/nginx/templates/dlfp.conf.template index a07ae40e3..cb0b3cfd9 100644 --- a/deployment/nginx/templates/dlfp.conf.template +++ b/deployment/nginx/templates/dlfp.conf.template @@ -1,6 +1,6 @@ -server { - listen 80; - listen [::]:80; +server { + listen 8080; + listen [::]:8080; server_name ${DOMAIN}; @@ -14,6 +14,11 @@ server { root /var/linuxfr/uploads; } + # Only used for health check command line in compose.yaml + location /img/status { + proxy_pass http://linuxfr-img:8000/status; + } + location /img/ { proxy_pass http://linuxfr-img:8000; } diff --git a/deployment/nginx/templates/image.dlfp.conf.template b/deployment/nginx/templates/image.dlfp.conf.template index 35f53c974..e2454d8ab 100644 --- a/deployment/nginx/templates/image.dlfp.conf.template +++ b/deployment/nginx/templates/image.dlfp.conf.template @@ -1,6 +1,6 @@ server { - listen 80; - listen [::]:80; + listen 8080; + listen [::]:8080; server_name ${IMAGE_DOMAIN};