diff --git a/examples/multi-node-production-icl/group_vars/artemis_cluster.yml b/examples/multi-node-production-icl/group_vars/artemis_cluster.yml index 99281b7..fac1b15 100644 --- a/examples/multi-node-production-icl/group_vars/artemis_cluster.yml +++ b/examples/multi-node-production-icl/group_vars/artemis_cluster.yml @@ -53,11 +53,14 @@ continuous_integration: ############################################################################## proxy_generate_dh_param: false -proxy_ssl_certificate_path: # FIXME fullchain.pem -proxy_ssl_certificate_key_path: # FIXME privkey.pem +servers: + - name: "_" + ssl_certificate_path: # FIXME fullchain.pem + ssl_certificate_key_path: # FIXME privkey.pem + default_server: true firewall_hostgroup: default -proxy_site_template: artemis # Name of the site loaded within nginx +proxy_forward_ssh: true ############################################################################## # Broker and Registry Configuration diff --git a/examples/multi-node-production-icl/playbooks/artemis-cluster-broker.yml b/examples/multi-node-production-icl/playbooks/artemis-cluster-broker.yml index d8671e7..61b2489 100644 --- a/examples/multi-node-production-icl/playbooks/artemis-cluster-broker.yml +++ b/examples/multi-node-production-icl/playbooks/artemis-cluster-broker.yml @@ -8,10 +8,13 @@ - role: ls1intum.artemis.proxy vars: - proxy_site_template: reverse_proxy + proxy_forward_ssh: false proxy_generate_dh_param: "{{ broker.proxy.generate_dh_param }}" - proxy_ssl_certificate_path: "{{ broker.proxy.ssl_certificate_path }}" - proxy_ssl_certificate_key_path: "{{ broker.proxy.ssl_certificate_key_path }}" + servers: + - name: "_" + ssl_certificate_path: "{{ broker.proxy.ssl_certificate_path }}" + ssl_certificate_key_path: "{{ broker.proxy.ssl_certificate_key_path }}" + default_server: true proxy_target_port: 8761 - role: ls1intum.artemis.firewall diff --git a/examples/multi-node-production-icl/playbooks/artemis-cluster-registry.yml b/examples/multi-node-production-icl/playbooks/artemis-cluster-registry.yml index fad86f1..1680155 100644 --- a/examples/multi-node-production-icl/playbooks/artemis-cluster-registry.yml +++ b/examples/multi-node-production-icl/playbooks/artemis-cluster-registry.yml @@ -9,10 +9,13 @@ - role: ls1intum.artemis.proxy tags: proxy vars: - proxy_site_template: reverse_proxy + proxy_forward_ssh: false proxy_generate_dh_param: "{{ registry.proxy.generate_dh_param }}" - proxy_ssl_certificate_path: "{{ registry.proxy.ssl_certificate_path }}" - proxy_ssl_certificate_key_path: "{{ registry.proxy.ssl_certificate_key_path }}" + servers: + - name: "_" + ssl_certificate_path: "{{ broker.proxy.ssl_certificate_path }}" + ssl_certificate_key_path: "{{ broker.proxy.ssl_certificate_key_path }}" + default_server: true proxy_target_port: 8761 - role: ls1intum.artemis.firewall diff --git a/roles/artemis/defaults/main.yml b/roles/artemis/defaults/main.yml index a8ca5b0..fd02a2f 100644 --- a/roles/artemis/defaults/main.yml +++ b/roles/artemis/defaults/main.yml @@ -57,7 +57,7 @@ artemis_notification_from: "Artemis Notification" artemis_telemetry_enabled: true artemis_send_admin_details: true -artemis_telemetry_destination: "telemetry.artemis.cit.tum.de" +artemis_telemetry_destination: "https://telemetry.artemis.cit.tum.de" artemis_working_directory: "/opt/artemis" artemis_repo_basepath: "." @@ -113,6 +113,19 @@ enable_science_event_logging: false #theia: # portal_url: https://theia-yannik.k8s.ase.cit.tum.de +# images: +# java: +# Java-17: "java-17-latest" +# c: +# C: "c-latest" +# javascript: +# Javascript: "javascript-latest" +# ocaml: +# Ocaml: "ocaml-latest" +# python: +# Python: "python-latest" +# rust: +# Rust: "rust-latest" # If the password of some users is stored externally, you need to provide a name and the reset links. They will be displayed as a hint in the reset form of Artemis. # You need to at least provide the provider and the English reset link. @@ -232,6 +245,9 @@ hazelcast_address: "{% if is_multinode_install is defined and is_multinode_insta artemis_eureka_urls: "{% if registry.url is defined and registry.url is not none %}http://admin:${jhipster.registry.password}@{{ registry.url }}:8761/eureka/{% endif %}" artemis_eureka_instance_id: "{{ node_id }}" +node_short_name: unnamed-artemis-node +node_display_name: Unnamed Artemis Node + ############################################################################## # Iris Configuration ############################################################################## diff --git a/roles/artemis/tasks/artemis_configuration.yml b/roles/artemis/tasks/artemis_configuration.yml index c8da602..14ae204 100644 --- a/roles/artemis/tasks/artemis_configuration.yml +++ b/roles/artemis/tasks/artemis_configuration.yml @@ -96,7 +96,7 @@ mode: '0775' owner: "{{ artemis_user_name }}" group: "{{ artemis_user_group }}" - when: artemis_data_export_path is not none and artemis_data_export_path != "" + when: artemis_data_export_path is not none and artemis_data_export_path != "" and artemis_computed_is_core_node - name: Set permissions for artemis data-export directory become: true @@ -106,7 +106,7 @@ recurse: true owner: "{{ artemis_user_name }}" group: "{{ artemis_user_group }}" - when: artemis_data_export_path is not none and artemis_data_export_path != "" + when: artemis_data_export_path is not none and artemis_data_export_path != "" and artemis_computed_is_core_node - name: Add artemis user to docker group become: true diff --git a/roles/artemis/templates/application-prod.yml.j2 b/roles/artemis/templates/application-prod.yml.j2 index 0698d2c..f92386a 100644 --- a/roles/artemis/templates/application-prod.yml.j2 +++ b/roles/artemis/templates/application-prod.yml.j2 @@ -258,6 +258,9 @@ artemis: expiry-days: {{ continuous_integration.localci.image_cleanup.expiry_days }} cleanup-schedule-time: {{ continuous_integration.localci.image_cleanup.schedule_time }} {% endif %} + build-agent: + short-name: {{ node_short_name }} + display-name: {{ node_display_name }} {% endif %} git: @@ -309,8 +312,8 @@ artemis: {% endif %} telemetry: - enabled: {{ artemis_telemetry_enabled }} - sendAdminDetails: {{ artemis_send_admin_details }} + enabled: {{ artemis_telemetry_enabled | lower }} + sendAdminDetails: {{ artemis_send_admin_details | lower }} destination: {{ artemis_telemetry_destination }} {% endif %} @@ -319,6 +322,15 @@ theia: {% if theia.portal_url is defined and theia.portal_url is not none %} portal-url: {{ theia.portal_url }} {% endif %} +{% if theia.images is defined and theia.images is not none %} + images: +{% for programming_language_key, programming_language_value in theia.images.items() %} + {{ programming_language_key }}: +{% for image_key, image_value in programming_language_value.items() %} + {{ image_key }}: {{ image_value }} +{% endfor %} +{% endfor %} +{% endif %} {% endif %} {% if aeolus.url is defined and aeolus.url is not none %} diff --git a/roles/artemis/templates/artemis.env.j2 b/roles/artemis/templates/artemis.env.j2 index f7396b0..c4ebcab 100644 --- a/roles/artemis/templates/artemis.env.j2 +++ b/roles/artemis/templates/artemis.env.j2 @@ -178,6 +178,8 @@ ARTEMIS_CONTINUOUSINTEGRATION_IMAGECLEANUP_ENABLED='true' ARTEMIS_CONTINUOUSINTEGRATION_IMAGECLEANUP_EXPIRYDAYS='{{ continuous_integration.localci.image_cleanup.expiry_days }}' ARTEMIS_CONTINUOUSINTEGRATION_IMAGECLEANUP_CLEANUPSCHEDULETIME='{{ continuous_integration.localci.image_cleanup.schedule_time }}' {% endif %} +ARTEMIS_CONTINUOUSINTEGRATION_BUILDAGENT_SHORTNAME='{{ node_short_name }}' +ARTEMIS_CONTINUOUSINTEGRATION_BUILDAGENT_DISPLAYNAME='{{ node_display_name }}' {% endif %} {% if continuous_integration.gitlabci is defined %} ARTEMIS_CONTINUOUSINTEGRATION_BUILDTIMEOUT=30 @@ -210,13 +212,20 @@ ARTEMIS_IRIS_SECRETTOKEN='{{ iris.secret }}' {% if enable_science_event_logging is defined %} ARTEMIS_SCIENCE_EVENTLOGGING_ENABLE='{{ enable_science_event_logging | lower }}' {% endif %} -ARTEMIS_TELEMETRY_ENABLED='{{ artemis_telemetry_enabled }}' -ARTEMIS_TELEMETRY_SENDADMINDETAILS='{{ artemis_send_admin_details }}' +ARTEMIS_TELEMETRY_ENABLED='{{ artemis_telemetry_enabled | lower }}' +ARTEMIS_TELEMETRY_SENDADMINDETAILS='{{ artemis_send_admin_details | lower }}' ARTEMIS_TELEMETRY_DESTINATION='{{ artemis_telemetry_destination }}' {% if theia is defined and theia is not none %} {% if theia.portal_url is defined and theia.portal_url is not none %} THEIA_PORTALURL='{{ theia.portal_url }}' {% endif %} +{% if theia.images is defined and theia.images is not none %} +{% for programming_language_key, programming_language_value in theia.images.items() %} +{% for image_key, image_value in programming_language_value.items() %} +THEIA_IMAGES_{{ programming_language_key | upper | regex_replace ("[^A-Z0-9]","") }}_{{ image_key | upper | regex_replace ("[^A-Z0-9]","") }}='{{ image_value }}' +{% endfor %} +{% endfor %} +{% endif %} {% endif %} {% if aeolus.url is defined and aeolus.url is not none %} AEOLUS_URL='{{ aeolus.url }}' diff --git a/roles/artemis/templates/node.env.j2 b/roles/artemis/templates/node.env.j2 index 6f752a7..13d2469 100644 --- a/roles/artemis/templates/node.env.j2 +++ b/roles/artemis/templates/node.env.j2 @@ -2,3 +2,5 @@ SPRING_PROFILES_ACTIVE='{{ artemis_spring_profiles }}{% if docker_node_id == 1 % EUREKA_INSTANCE_INSTANCEID='Artemis:{{ docker_node_id }}' EUREKA_INSTANCE_HOSTNAME='artemis-app-node-{{ docker_node_id }}' SPRING_HAZELCAST_INTERFACE='artemis-app-node-{{ docker_node_id }}' +ARTEMIS_CONTINUOUSINTEGRATION_BUILDAGENT_SHORTNAME='artemis-node-{{ docker_node_id }}' +ARTEMIS_CONTINUOUSINTEGRATION_BUILDAGENT_DISPLAYNAME='Artemis Node {{ docker_node_id }}' diff --git a/roles/gitlab/examples/gitlab-playbook.yml b/roles/gitlab/examples/gitlab-playbook.yml index 169bb5a..9ff7fc1 100644 --- a/roles/gitlab/examples/gitlab-playbook.yml +++ b/roles/gitlab/examples/gitlab-playbook.yml @@ -8,5 +8,5 @@ become: true vars: proxy_target_port: 8081 - proxy_site_template: reverse_proxy + proxy_forward_ssh: false - role: ../../gitlab diff --git a/roles/jenkins/examples/jenkins-playbook.yml b/roles/jenkins/examples/jenkins-playbook.yml index b72687f..311f6a3 100644 --- a/roles/jenkins/examples/jenkins-playbook.yml +++ b/roles/jenkins/examples/jenkins-playbook.yml @@ -8,5 +8,5 @@ become: true vars: proxy_target_port: 8082 - proxy_site_template: reverse_proxy + proxy_forward_ssh: false - role: ../../jenkins diff --git a/roles/proxy/defaults/main.yml b/roles/proxy/defaults/main.yml index 9895b44..f68b2ca 100644 --- a/roles/proxy/defaults/main.yml +++ b/roles/proxy/defaults/main.yml @@ -1,39 +1,42 @@ -proxy_ssl_certificate_path: -proxy_ssl_certificate_key_path: +servers: + - name: + ssl_certificate_path: + ssl_certificate_key_path: + default_server: true -proxy_resolver: "127.0.0.53 valid=300s" # Nodes for load balancing; Either define a host-group or manually list all nodes #proxy_available_nodes: "{{ groups.artemisnodes }}" # will not work anymore proxy_available_nodes: - hostname: 127.0.0.1 - # Service Port on nodes for load balancing; If differing for each node fall back to # manual list of proxy_available_nodes and comment out proxy_target_port variable declaration proxy_target_port: 8080 +# Port forwarding configuration of Artemis nodes for SSH Git communication with Artemis ICL LocalVC +proxy_forward_ssh: true + # Protocol used to communicate with nodes (either http or https) proxy_node_protocol: http +# Used for the /mailto enpoint - Has to be a valid mail address. +proxy_mailto: + # /etc/nginx/sites-available/artemis.conf # Uncomment to change load balancing method from default (which is round robin) # Can be "least_conn" or "ip_hash" #proxy_load_balancing_method: ip_hash +proxy_resolver: "127.0.0.53 valid=300s" + proxy_worker_rlmmiit_nofile: 30000 proxy_worker_connections: 20000 proxy_server_names_hash_bucket_size: 256 -proxy_site_template: artemis - proxy_generate_dh_param: true -# Used for the /mailto enpoint - Has to be a valid mail address. -proxy_mailto: - - proxy_send_timeout: "900s" proxy_read_timeout: "900s" fastcgi_send_timeout: "900s" diff --git a/roles/proxy/tasks/deprecations.yml b/roles/proxy/tasks/deprecations.yml new file mode 100644 index 0000000..8630a0e --- /dev/null +++ b/roles/proxy/tasks/deprecations.yml @@ -0,0 +1,23 @@ +- name: Display deprecation notice + debug: + msg: "DEPRECATION NOTICE: The variable 'proxy_site_template' is being deprecated. Please use 'proxy_forward_ssh' instead. See https://github.com/ls1intum/artemis-ansible-collection/pull/70 for additional information." + when: proxy_site_template is defined + +- name: Set default values for deprecated variables + set_fact: + proxy_forward_ssh: "{{ proxy_site_template == 'artemis' }}" + when: proxy_site_template is defined + +- name: Display deprecation notice + debug: + msg: "DEPRECATION NOTICE: The variable 'proxy_ssl_certificate_path' and 'proxy_ssl_certificate_key_path' is being deprecated. Please use the 'server' list instead. See https://github.com/ls1intum/artemis-ansible-collection/pull/70 for additional information." + when: proxy_ssl_certificate_path is defined or proxy_ssl_certificate_key_path is defined + +- name: Set default values for deprecated variables + set_fact: + servers: + - name: "_" + ssl_certificate_path: "{{ proxy_ssl_certificate_path }}" + ssl_certificate_key_path: "{{ proxy_ssl_certificate_key_path }}" + default_server: true + when: proxy_ssl_certificate_path is defined or proxy_ssl_certificate_key_path is defined diff --git a/roles/proxy/tasks/main.yml b/roles/proxy/tasks/main.yml index 6a71684..e77844a 100644 --- a/roles/proxy/tasks/main.yml +++ b/roles/proxy/tasks/main.yml @@ -1,3 +1,11 @@ +# Check for compatible Ansible version. +- name: Check for compatible Ansible version. + assert: + that: ansible_version.full is version_compare('2.16', '>=') + msg: You need Ansible version 2.16 or higher. + +- include_tasks: deprecations.yml + # Setup nginx proxy - include_tasks: nginx.yml diff --git a/roles/proxy/tasks/nginx.yml b/roles/proxy/tasks/nginx.yml index 2de2105..6d64c40 100644 --- a/roles/proxy/tasks/nginx.yml +++ b/roles/proxy/tasks/nginx.yml @@ -1,7 +1,7 @@ - name: Add repo for the latest stable ngnix version become: true block: - - name: ngnix |no apt key + - name: ngnix | no apt key ansible.builtin.get_url: url: http://nginx.org/keys/nginx_signing.key dest: /etc/apt/trusted.gpg.d/nginx.asc @@ -17,7 +17,6 @@ name: nginx state: latest update_cache: yes - notify: restart nginx - name: Enable nginx service @@ -114,7 +113,7 @@ proxy_pass artemis_ssh; } } - when: proxy_site_template == "artemis" + when: proxy_forward_ssh notify: restart nginx - name: Copy artemis-ssh-upstream.conf @@ -123,6 +122,7 @@ src: artemis-ssh-upstream.conf.j2 dest: /etc/nginx/artemis-ssh-upstream.conf mode: 0644 + when: proxy_forward_ssh notify: restart nginx - name: Copy timeouts.conf @@ -133,30 +133,34 @@ mode: 0644 notify: restart nginx -- name: Copy {{ proxy_site_template }}.conf +- name: Copy proxy.conf become: true template: - src: nginx_{{ proxy_site_template }}.conf.j2 - dest: /etc/nginx/sites-available/{{ proxy_site_template }}.conf + src: nginx_proxy.conf.j2 + dest: /etc/nginx/sites-available/proxy.conf mode: 0644 notify: reload nginx -- name: Enable {{ proxy_site_template }} site config +- name: Enable proxy site config become: true file: - src: /etc/nginx/sites-available/{{ proxy_site_template }}.conf - dest: /etc/nginx/sites-enabled/{{ proxy_site_template }}.conf + src: /etc/nginx/sites-available/proxy.conf + dest: /etc/nginx/sites-enabled/proxy.conf owner: root group: root state: link notify: reload nginx -- name: Disable default site config +- name: Disable default and legacy site config become: true file: - dest: /etc/nginx/sites-enabled/default + dest: "/etc/nginx/sites-enabled/{{ item }}" state: absent notify: reload nginx + with_items: + - "default" + - "artemis.conf" + - "reverse_proxy.conf" - name: Ensure old 502.html error page is removed become: true diff --git a/roles/proxy/templates/nginx_artemis.conf.j2 b/roles/proxy/templates/nginx_proxy.conf.j2 similarity index 85% rename from roles/proxy/templates/nginx_artemis.conf.j2 rename to roles/proxy/templates/nginx_proxy.conf.j2 index e346b28..08050e0 100644 --- a/roles/proxy/templates/nginx_artemis.conf.j2 +++ b/roles/proxy/templates/nginx_proxy.conf.j2 @@ -1,7 +1,7 @@ {{ ansible_managed | comment }} # Load balancing -upstream artemis { +upstream app { {% if proxy_load_balancing_method is defined %} {{ proxy_load_balancing_method }}; {% endif %} @@ -30,19 +30,20 @@ server { return 301 https://$host$request_uri; } +{% for server in servers %} server { - listen 443 ssl; - listen 443 quic reuseport; - listen [::]:443 ssl; - listen [::]:443 quic reuseport; + listen 443 ssl{% if server.default_server %} default_server{% endif %}; + listen 443 quic{% if loop.index == 1 %} reuseport{% endif %}; + listen [::]:443 ssl{% if server.default_server %} default_server{% endif %}; + listen [::]:443 quic{% if loop.index == 1 %} reuseport{% endif %}; http2 on; http3 on; http3_hq on; quic_retry on; - server_name _; - ssl_certificate {{ proxy_ssl_certificate_path }}; - ssl_certificate_key {{ proxy_ssl_certificate_key_path }}; + server_name {{ server.name }}; + ssl_certificate {{ server.ssl_certificate_path }}; + ssl_certificate_key {{ server.ssl_certificate_key_path }}; ssl_protocols TLSv1.2 TLSv1.3; {% if proxy_generate_dh_param|bool == true %}ssl_dhparam /etc/nginx/dhparam.pem;{% endif %} ssl_prefer_server_ciphers on; @@ -62,7 +63,7 @@ server { client_body_buffer_size 1m; location / { - proxy_pass {{ proxy_node_protocol }}://artemis; + proxy_pass {{ proxy_node_protocol }}://app; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; @@ -93,7 +94,7 @@ server { {% endif %} location /api/authenticate { - proxy_pass http://artemis/api/authenticate; + proxy_pass http://app/api/authenticate; # For a given violation of the rate limit defined in the zone # * the first 2 (delay) requests will be allowed without delay # * the next (burst - delay) request waits until it fits in the rate limit @@ -113,3 +114,5 @@ server { internal; } } + +{% endfor %} diff --git a/roles/proxy/templates/nginx_reverse_proxy.conf.j2 b/roles/proxy/templates/nginx_reverse_proxy.conf.j2 deleted file mode 100644 index 311129d..0000000 --- a/roles/proxy/templates/nginx_reverse_proxy.conf.j2 +++ /dev/null @@ -1,70 +0,0 @@ -{{ ansible_managed | comment }} - -log_format quic '$remote_addr - $remote_user [$time_local] ' - '"$request" $status $body_bytes_sent ' - '"$http_referer" "$http_user_agent" "$http3"'; - -access_log quic; - -server { - listen 80 default_server; - listen [::]:80 default_server; - server_name _; - - return 301 https://$host$request_uri; -} - -server { - listen 443 ssl; - listen 443 quic reuseport; - listen [::]:443 ssl; - listen [::]:443 quic reuseport; - http2 on; - http3 on; - http3_hq on; - quic_retry on; - - server_name _; - ssl_certificate {{ proxy_ssl_certificate_path }}; - ssl_certificate_key {{ proxy_ssl_certificate_key_path }}; - ssl_protocols TLSv1.2 TLSv1.3; - {% if proxy_generate_dh_param|bool == true %}ssl_dhparam /etc/nginx/dhparam.pem;{% endif %} - ssl_prefer_server_ciphers on; - ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256'; - ssl_ecdh_curve secp384r1; - ssl_session_timeout 10m; - ssl_session_cache shared:SSL:10m; - ssl_session_tickets off; - ssl_stapling on; - ssl_stapling_verify on; -# ssl_early_data on; - quic_gso on; - resolver {{ proxy_resolver }}; - resolver_timeout 5s; - add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"; - add_header X-Frame-Options DENY; - add_header Referrer-Policy same-origin; - add_header Content-Security-Policy "script-src 'self' 'unsafe-inline' 'unsafe-eval'"; - client_max_body_size 10m; - client_body_buffer_size 1m; - - location / { - proxy_pass http://localhost:{{ proxy_target_port }}; - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection 'upgrade'; - proxy_set_header Host $host; -# proxy_set_header Early-Data $ssl_early_data; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_cache_bypass $http_upgrade; - # used to advertise the availability of HTTP/3 - add_header alt-svc 'h3=":443"; ma=2592000,h3-29=":443"; ma=2592000'; - } - - error_page 502 =503 /503.html; - location /503.html { - root /usr/share/nginx/html; - internal; - } -} diff --git a/roles/registry/defaults/main.yml b/roles/registry/defaults/main.yml index 0ae36b8..6024be3 100644 --- a/roles/registry/defaults/main.yml +++ b/roles/registry/defaults/main.yml @@ -35,5 +35,5 @@ registry_bootstrap_prod_file: "{{ registry_working_directory }}/bootstrap-prod.y registry_application_file: "{{ registry_working_directory }}/config-server/application.yml" registry_instance_id: registry:1 -proxy_site_template: reverse_proxy # Name of the site loaded within nginx proxy_target_port: 8761 +proxy_forward_ssh: false