Hello,
I'm a new intern at No Parking and I'm currently working on my first FreeBSD-related project.
The goal is to package Visio (the video conferencing application from the French government's La Suite collaborative platform) as a FreeBSD port. I've already managed to install it manually, but I'm now learning how to turn it into a proper port and build it with poudriere.
I'm new to the FreeBSD ports ecosystem and would appreciate any advice on the best way to proceed.
The project involves four different components: Keycloak (which already exists as a port, net/keycloak), LiveKit, Meet, and Apache. At the moment, I'm having the most difficulties with the Meet package, especially regarding its dependencies and the overall porting process.
Below are the steps I performed manually. There may be mistakes, and I may have omitted some details that I forgot to document:
Since this is also my first time posting on the FreeBSD forums, please let me know if I should provide more details or if there is a better place to ask this kind of question.
Thank you for your time and any guidance you can provide.
I'm a new intern at No Parking and I'm currently working on my first FreeBSD-related project.
The goal is to package Visio (the video conferencing application from the French government's La Suite collaborative platform) as a FreeBSD port. I've already managed to install it manually, but I'm now learning how to turn it into a proper port and build it with poudriere.
I'm new to the FreeBSD ports ecosystem and would appreciate any advice on the best way to proceed.
The project involves four different components: Keycloak (which already exists as a port, net/keycloak), LiveKit, Meet, and Apache. At the moment, I'm having the most difficulties with the Meet package, especially regarding its dependencies and the overall porting process.
Makefile:
PORTNAME= meet
DISTVERSIONPREFIX= v
DISTVERSION= 1.17.0
CATEGORIES= www net
MAINTAINER= helene@noparking.net
COMMENT= La Suite Numérique -> Meet
WWW= https://github.com/suitenumerique/meet
LICENSE= MIT
USE_RC_SUBR= meet
USES= python:3.11+ nodejs:24
USE_PYTHON= flavors
BUILD_DEPENDS= ${LOCALBASE}/bin/npm:www/npm-node24
RUN_DEPENDS= gunicorn:www/py-gunicorn \
postgresql16-client:databases/postgresql16-client \
livekit-server:net/livekit \
redis-cli:databases/redis \
${PYTHON_PKGNAMEPREFIX}django52>=0:www/py-django52 \
${PYTHON_PKGNAMEPREFIX}gunicorn>=0:www/py-gunicorn \
${PYTHON_PKGNAMEPREFIX}redis>=0:databases/py-redis \
${PYTHON_PKGNAMEPREFIX}dj-database-url>=0:www/py-dj-database-url \
${PYTHON_PKGNAMEPREFIX}django-configurations>=0:www/py-django-configurations \
${PYTHON_PKGNAMEPREFIX}django-cors-headers>=0:www/py-django-cors-headers \
${PYTHON_PKGNAMEPREFIX}django-countries>=0:www/py-django-countries \
${PYTHON_PKGNAMEPREFIX}django-filter>=0:www/py-django-filter \
${PYTHON_PKGNAMEPREFIX}django-redis>=0:www/py-django-redis \
${PYTHON_PKGNAMEPREFIX}django-storages>=0:www/py-django-storages \
${PYTHON_PKGNAMEPREFIX}django-timezone-field>=0:www/py-django-timezone-field \
${PYTHON_PKGNAMEPREFIX}django-pydantic-field>=0:www/py-django-pydantic-field \
${PYTHON_PKGNAMEPREFIX}djangorestframework>=0:www/py-djangorestframework \
${PYTHON_PKGNAMEPREFIX}drf-spectacular>=0:www/py-drf-spectacular \
${PYTHON_PKGNAMEPREFIX}factory-boy>=0:devel/py-factory-boy \
${PYTHON_PKGNAMEPREFIX}jsonschema>=0:devel/py-jsonschema \
${PYTHON_PKGNAMEPREFIX}markdown>=0:textproc/py-markdown \
${PYTHON_PKGNAMEPREFIX}PyJWT>=0:security/py-pyjwt \
${PYTHON_PKGNAMEPREFIX}python-magic>=0:devel/py-magic \
${PYTHON_PKGNAMEPREFIX}requests>=0:www/py-requests \
${PYTHON_PKGNAMEPREFIX}sentry-sdk>=0:devel/py-sentry-sdk \
${PYTHON_PKGNAMEPREFIX}whitenoise>=0:www/py-whitenoise \
${PYTHON_PKGNAMEPREFIX}mozilla-django-oidc>=0:www/py-mozilla-django-oidc \
${PYTHON_PKGNAMEPREFIX}aiohttp>=0:www/py-aiohttp \
${PYTHON_PKGNAMEPREFIX}urllib3>=0:www/py-urllib3 \
${PYTHON_PKGNAMEPREFIX}boto3>=0:devel/py-boto3 \
${PYTHON_PKGNAMEPREFIX}python-frontmatter>=0:py-python-frontmatter \
USE_GITHUB= yes
GH_ACCOUNT= suitenumerique
GH_PROJECT= meet
PREFIX?= /usr/local
MEET_DIR= ${PREFIX}/meet
PLIST_SUB= MEET_DIR=${MEET_DIR}
SUB_LIST= MEET_DIR=${MEET_DIR} \
PREFIX=${PREFIX}
SUB_FILES= pkg-message
USERS= meet
GROUPS= meet
do-build:
@${ECHO_MSG} "===> Build du frontend Meet..."
cd ${WRKSRC}/src/frontend && \
HOME=${WRKDIR} \
npm_config_cache=${WRKDIR}/.npm-cache \
${LOCALBASE}/bin/npm install --no-package-lock --verbose
@${ECHO_MSG} "===> npm install terminé, lancement du build..."
cd ${WRKSRC}/src/frontend && \
HOME=${WRKDIR} \
${LOCALBASE}/bin/npm run build
@${ECHO_MSG} "===> Vérification du dist..."
ls ${WRKSRC}/src/frontend/dist
do-install:
${MKDIR} ${STAGEDIR}${MEET_DIR}
${MKDIR} ${STAGEDIR}${MEET_DIR}/src
${MKDIR} ${STAGEDIR}/var/log/meet
${MKDIR} ${STAGEDIR}/var/run/meet
cd ${WRKSRC}/src/backend && \
${COPYTREE_SHARE} . ${STAGEDIR}${MEET_DIR}/src/backend
cd ${WRKSRC}/src/frontend/dist && \
${COPYTREE_SHARE} . ${STAGEDIR}${MEET_DIR}/src/frontend/dist
${INSTALL_DATA} ${FILESDIR}/meet.env.sample \
${STAGEDIR}${MEET_DIR}/src/backend/.env.sample
${MKDIR} ${STAGEDIR}${PREFIX}/etc/rc.d
${INSTALL_SCRIPT} ${FILESDIR}/meet_backend.rc \
${STAGEDIR}${PREFIX}/etc/rc.d/meet_backend
post-install:
cd ${STAGEDIR} && \
find .${MEET_DIR} -type f | \
sed 's|^\./usr/local/||' | sort >> ${TMPPLIST}
echo "@owner meet" >> ${TMPPLIST}
echo "@group meet" >> ${TMPPLIST}
echo "@dir /var/log/meet" >> ${TMPPLIST}
echo "@dir /var/run/meet" >> ${TMPPLIST}
echo "@owner root" >> ${TMPPLIST}
echo "@group wheel" >> ${TMPPLIST}
.include <bsd.port.mk>
Below are the steps I performed manually. There may be mistakes, and I may have omitted some details that I forgot to document:
Markdown (GitHub flavored):
## Installer les dependances
sudo pkg update
sudo pkg install python311 py311-pip py311-virtualenv py311-gunicorn node npm git go gmake pkgconf apache24 postgresql16-server postgresql16-client redis
## Activer les services
### Postgresql
sysrc postgresql_enable="YES"
service postgresql initdb
service postgresql start
### Redis
sysrc redis_enable="YES"
service redis start
# Créer la base et l'utilisateur
psql -U postgres <<EOF
CREATE USER meet WITH PASSWORD 'toor';
CREATE DATABASE meet OWNER meet;
EOF
## Compiler LiveKit
git clone https://github.com/livekit/livekit /opt/livekit
cd /opt/livekit
go build -o /usr/local/bin/livekit-server ./cmd/server -> si a marche checker binaire : ls -lh /usr/local/bin/livekit-server && livekit-server --version
touch /usr/local/etc/livekit.yaml
```
port: 7880
rtc:
tcp_port: 7881
udp_port: 7882
use_external_ip: true
redis:
address: 127.0.0.1:6379
keys:
monApiKey: secret
turn:
enabled: true
domain: 10.0.0.218
tls_port: 5349
```
Pour tester : livekit-server --config /usr/local/etc/livekit.yaml --dev
## Keycloak (OIDC — obligatoire) -> Meet utilise OpenID Connect pour l'authentification
Keycloak -> Java
pkg install openjdk21
fetch https://github.com/keycloak/keycloak/releases/download/26.0.0/keycloak-26.0.0.tar.gz
tar xf keycloak-26.0.0.tar.gz -C /opt/
cd /opt/keycloak-26.0.0
bin/kc.sh start-dev --http-port=8080 & # mod dev
pour tester sur une autre machine
export KC_BOOTSTRAP_ADMIN_USERNAME=admin
export KC_BOOTSTRAP_ADMIN_PASSWORD=admin
Et dans Keycloak (http://10.0.0.218:8080) :
Créer un realm meet
Créer un client meet-client (type: confidential, OIDC)
Noter le client_id et le client_secret
Créer un utilisateur test
name: meet client
client_id: 12
## Backend
git clone https://github.com/suitenumerique/meet /opt/meet
cd /opt/meet/src/backend
### Virtualenv Python
python3.11 -m venv venv
. venv/bin/activate
pip install -r requirements.txt
fichier d'env:
touch /opt/meet/src/backend/.env
```sh
# Django
DJANGO_SECRET_KEY=une_cle_tres_longue_et_aleatoire_50_chars
DJANGO_ALLOWED_HOSTS=meet.noparking.tld,10.0.0.218
DJANGO_SETTINGS_MODULE=meet.settings
# Base de données
DB_HOST=localhost
DB_NAME=meet
DB_USER=dinum
DB_PASSWORD=toor
DB_PORT=5432
# Redis
REDIS_URL=redis://127.0.0.1:6379/0 (change to valkey)
# LiveKit
LIVEKIT_API_KEY=monApiKey
LIVEKIT_API_SECRET=secret
LIVEKIT_API_URL=ws://10.0.0.218
# OIDC (Keycloak)
OIDC_RP_CLIENT_ID=helene
OIDC_RP_CLIENT_SECRET=5Oi8Sp95Mi1FPXd6ZIlLkuddKQnzNeTz
OIDC_OP_AUTHORIZATION_ENDPOINT=https://10.0.0.218:8443/realms/meet/protocol/openid-connect/auth
OIDC_OP_TOKEN_ENDPOINT=https://10.0.0.218:8443/realms/meet/protocol/openid-connect/token
OIDC_OP_USER_ENDPOINT=https://10.0.0.218:8443/realms/meet/protocol/openid-connect/userinfo
OIDC_OP_JWKS_ENDPOINT=https://10.0.0.218:8443/realms/meet/protocol/openid-connect/certs
```
# Migrations et superuser
echo 'DJANGO_CONFIGURATION=Development' >> /opt/meet/src/backend/.env
python manage.py migrate / venv/bin/python -m configurations.management migrate
python manage.py createsuperuser --email helene@noparking.net / venv/bin/python -m configurations.management createsuperuser --email helene@noparking.net
export DJANGO_SETTINGS_MODULE=meet.settings_dev
pour tester : python manage.py runserver 0.0.0.0:8000
venv/bin/python -v -m configurations.management runserver 0.0.0.0:8000
venv/bin/gunicorn meet.wsgi:application \
--bind 0.0.0.0:8000 \
--worker-tmp-dir /tmp \
--workers 2
set -a && . .env && set +a && export DJANGO_CONFIGURATION=Development && export DJANGO_SETTINGS_MODULE=meet.settings && venv/bin/python -m configurations.management migrate --verbosity=3 2>&1
run le front
cd /opt/meet/src/frontend
npm install
npm run build
# Apache
dans /usr/local/etc/apache24/httpd.conf décommenter :
LoadModule proxy_module libexec/apache24/mod_proxy.so
LoadModule proxy_http_module libexec/apache24/mod_proxy_http.so
LoadModule proxy_wstunnel_module libexec/apache24/mod_proxy_wstunnel.so
LoadModule ssl_module libexec/apache24/mod_ssl.so
LoadModule rewrite_module libexec/apache24/mod_rewrite.so
LoadModule headers_module libexec/apache24/mod_headers.so
LoadModule ssl_module libexec/apache24/mod_ssl.so
Include etc/apache24/extra/httpd-vhosts.conf
Include etc/apache24/extra/httpd-ssl.conf
sudo apachectl configtest && sudo service apache24 restart
touch sites/meet.conf
```
<VirtualHost *:80>
ServerName 10.0.0.218
DocumentRoot /opt/meet/src/frontend/dist
<Directory /opt/meet/src/frontend/dist>
Options -Indexes
AllowOverride None
Require all granted
FallbackResource /index.html
</Directory>
ProxyPreserveHost On
ProxyPass /api/ http://127.0.0.1:8000/api/
ProxyPassReverse /api/ http://127.0.0.1:8000/api/
ProxyPass /admin/ http://127.0.0.1:8000/admin/
ProxyPassReverse /admin/ http://127.0.0.1:8000/admin/
ProxyPass /jwks http://127.0.0.1:8000/jwks
ProxyPassReverse /jwks http://127.0.0.1:8000/jwks
RewriteEngine On
RewriteCond %{HTTP:Upgrade} websocket [NC]
RewriteRule /livekit/(.*) ws://127.0.0.1:7880/$1 [P,L]
ProxyPass /livekit/ http://127.0.0.1:7880/
ProxyPassReverse /livekit/ http://127.0.0.1:7880/
</VirtualHost>
<VirtualHost *:443>
ServerName 10.0.0.218
SSLEngine On
SSLCertificateFile /usr/local/etc/ssl/meet.crt
SSLCertificateKeyFile /usr/local/etc/ssl/meet.key
DocumentRoot /opt/meet/src/frontend/dist
<Directory /opt/meet/src/frontend/dist>
Options -Indexes
AllowOverride None
Require all granted
FallbackResource /index.html
</Directory>
ProxyPreserveHost On
RequestHeader set X-Forwarded-Proto "https"
ProxyPass /api/ http://127.0.0.1:8000/api/
ProxyPassReverse /api/ http://127.0.0.1:8000/api/
ProxyPass /admin/ http://127.0.0.1:8000/admin/
ProxyPassReverse /admin/ http://127.0.0.1:8000/admin/
ProxyPass /jwks http://127.0.0.1:8000/jwks
ProxyPassReverse /jwks http://127.0.0.1:8000/jwks
RewriteEngine On
RewriteCond %{HTTP:Upgrade} websocket [NC]
RewriteRule /livekit/(.*) ws://127.0.0.1:7880/$1 [P,L]
ProxyPass /livekit/ http://127.0.0.1:7880/
ProxyPassReverse /livekit/ http://127.0.0.1:7880/
</VirtualHost>
```
Since this is also my first time posting on the FreeBSD forums, please let me know if I should provide more details or if there is a better place to ask this kind of question.
Thank you for your time and any guidance you can provide.