Setup authentik sso support
This commit is contained in:
@@ -74,3 +74,9 @@ MFA_ENABLED=true
|
||||
|
||||
# Enable DAV support (beta feature)
|
||||
DAV_ENABLED=true
|
||||
|
||||
# OIDC Configuration for Authentik
|
||||
AUTHENTIK_BASE_URL=
|
||||
AUTHENTIK_CLIENT_ID=
|
||||
AUTHENTIK_CLIENT_SECRET=
|
||||
AUTHENTIK_REDIRECT_URI=http://localhost:8080/auth/authentik/callback
|
||||
|
||||
@@ -142,6 +142,12 @@ DAV_ENABLED=true
|
||||
PASSPORT_PASSWORD_GRANT_CLIENT_ID=
|
||||
PASSPORT_PASSWORD_GRANT_CLIENT_SECRET=
|
||||
|
||||
# OIDC Authentication via Authentik
|
||||
AUTHENTIK_BASE_URL=
|
||||
AUTHENTIK_CLIENT_ID=
|
||||
AUTHENTIK_CLIENT_SECRET=
|
||||
AUTHENTIK_REDIRECT_URI="${APP_URL}/auth/authentik/callback"
|
||||
|
||||
# Allow to access general statistics about your instance through a public API
|
||||
# call
|
||||
ALLOW_STATISTICS_THROUGH_PUBLIC_API_ACCESS=false
|
||||
|
||||
@@ -40,7 +40,7 @@ class OAuthController extends Controller
|
||||
{
|
||||
$this->encrypter = $encrypter;
|
||||
|
||||
if (config('app.debug')) {
|
||||
if (config('app.debug') && class_exists('Barryvdh\Debugbar\Facades\Debugbar')) {
|
||||
Debugbar::disable();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,143 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Auth;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\User\User;
|
||||
use App\Models\Account\Account;
|
||||
use App\Helpers\RequestHelper;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Laravel\Socialite\Facades\Socialite;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class OIDCController extends Controller
|
||||
{
|
||||
/**
|
||||
* Redirect the user to the Authentik authentication page.
|
||||
*/
|
||||
public function redirectToProvider()
|
||||
{
|
||||
$driver = Socialite::driver('authentik');
|
||||
\Log::info('OIDC Redirect scopes', ['scopes' => $driver->getScopes()]);
|
||||
|
||||
return $driver
|
||||
->redirect();
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain the user information from Authentik.
|
||||
*/
|
||||
public function handleProviderCallback(Request $request)
|
||||
{
|
||||
\Log::info('OIDC Callback started', ['url' => $request->fullUrl(), 'params' => $request->all()]);
|
||||
|
||||
// Add early error handling
|
||||
if (!$request->has('code')) {
|
||||
\Log::error('OIDC Callback missing authorization code', ['params' => $request->all()]);
|
||||
return redirect('/login')->withErrors(['msg' => 'Authorization code missing. Please try again.']);
|
||||
}
|
||||
|
||||
try {
|
||||
$authentikUser = Socialite::driver('authentik')->user();
|
||||
\Log::info('OIDC User retrieved', [
|
||||
'email' => $authentikUser->email,
|
||||
'id' => $authentikUser->id,
|
||||
'name' => $authentikUser->name,
|
||||
'raw_user' => $authentikUser->user,
|
||||
'all_data' => $authentikUser->getRaw()
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
\Log::error('OIDC Authentication failed', ['error' => $e->getMessage()]);
|
||||
return redirect('/login')->withErrors(['msg' => 'Authentication failed. Please try again.']);
|
||||
}
|
||||
|
||||
// Check if user already exists by OIDC subject ID
|
||||
$user = User::where('oidc_sub', $authentikUser->id)->first();
|
||||
|
||||
if ($user) {
|
||||
\Log::info('OIDC User found by subject ID', ['user_id' => $user->id]);
|
||||
// Update user info from OIDC provider
|
||||
$this->updateUserOIDCInfo($user, $authentikUser);
|
||||
Auth::login($user);
|
||||
\Log::info('OIDC User logged in successfully', ['user_id' => $user->id]);
|
||||
return redirect()->intended('/dashboard');
|
||||
}
|
||||
|
||||
// Check if user exists by email (if email is available)
|
||||
if (!empty($authentikUser->email)) {
|
||||
$existingUser = User::where('email', $authentikUser->email)->first();
|
||||
|
||||
if ($existingUser) {
|
||||
\Log::info('OIDC User found by email', ['user_id' => $existingUser->id]);
|
||||
// Link existing user to OIDC provider
|
||||
$this->updateUserOIDCInfo($existingUser, $authentikUser);
|
||||
Auth::login($existingUser);
|
||||
\Log::info('OIDC Existing user logged in successfully', ['user_id' => $existingUser->id]);
|
||||
return redirect()->intended('/dashboard');
|
||||
}
|
||||
}
|
||||
|
||||
// Create new user
|
||||
\Log::info('OIDC Creating new user', ['email' => $authentikUser->email]);
|
||||
try {
|
||||
$user = $this->createUser($authentikUser);
|
||||
Auth::login($user);
|
||||
\Log::info('OIDC New user created and logged in successfully', ['user_id' => $user->id]);
|
||||
return redirect()->intended('/dashboard');
|
||||
} catch (\Exception $e) {
|
||||
\Log::error('OIDC User creation failed', ['error' => $e->getMessage()]);
|
||||
return redirect('/login')->withErrors(['msg' => 'User creation failed. Please try again.']);
|
||||
}
|
||||
} /**
|
||||
* Create a new user from OIDC provider data.
|
||||
*/
|
||||
private function createUser($authentikUser)
|
||||
{
|
||||
// Generate a unique username if name is not provided
|
||||
$firstName = $authentikUser->user['given_name'] ?? explode(' ', $authentikUser->name)[0] ?? 'User';
|
||||
$lastName = $authentikUser->user['family_name'] ?? (explode(' ', $authentikUser->name)[1] ?? '');
|
||||
|
||||
// Require email from OIDC provider
|
||||
if (empty($authentikUser->email)) {
|
||||
\Log::error('OIDC User missing email', ['user_id' => $authentikUser->id, 'raw_data' => $authentikUser->getRaw()]);
|
||||
throw new \Exception('Email not provided by OIDC provider');
|
||||
}
|
||||
$email = $authentikUser->email;
|
||||
|
||||
// Create account and user using Monica's default method
|
||||
// Generate a secure random password for OIDC users (they won't use it)
|
||||
$randomPassword = Str::random(32);
|
||||
|
||||
$account = \App\Models\Account\Account::createDefault(
|
||||
$firstName,
|
||||
$lastName,
|
||||
$email,
|
||||
$randomPassword,
|
||||
\App\Helpers\RequestHelper::ip(),
|
||||
'en' // Default locale
|
||||
);
|
||||
|
||||
// Get the created user
|
||||
$user = $account->users()->first();
|
||||
|
||||
// Mark email as verified for OIDC users (since they're authenticated via OIDC provider)
|
||||
$user->markEmailAsVerified();
|
||||
|
||||
// Update user with OIDC info
|
||||
$this->updateUserOIDCInfo($user, $authentikUser);
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update user with OIDC provider information.
|
||||
*/
|
||||
private function updateUserOIDCInfo(User $user, $authentikUser)
|
||||
{
|
||||
$user->update([
|
||||
'oidc_sub' => $authentikUser->id,
|
||||
'oidc_email' => $authentikUser->email,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -49,6 +49,8 @@ class User extends Authenticatable implements MustVerifyEmail, HasLocalePreferen
|
||||
'temperature_scale',
|
||||
'name_order',
|
||||
'google2fa_secret',
|
||||
'oidc_sub',
|
||||
'oidc_provider',
|
||||
];
|
||||
|
||||
/**
|
||||
|
||||
@@ -29,6 +29,11 @@ class AppServiceProvider extends ServiceProvider
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
// Register Authentik Socialite Provider
|
||||
\Illuminate\Support\Facades\Event::listen(function (\SocialiteProviders\Manager\SocialiteWasCalled $event) {
|
||||
$event->extendSocialite('authentik', \SocialiteProviders\Authentik\Provider::class);
|
||||
});
|
||||
|
||||
if (App::runningInConsole()) {
|
||||
Command::macro('exec', function (string $message, string $commandline) {
|
||||
// @codeCoverageIgnoreStart
|
||||
|
||||
@@ -18,6 +18,9 @@ class EventServiceProvider extends ServiceProvider
|
||||
\Illuminate\Auth\Events\PasswordReset::class => [
|
||||
\App\Listeners\LogoutUserDevices::class,
|
||||
],
|
||||
\SocialiteProviders\Manager\SocialiteWasCalled::class => [
|
||||
\SocialiteProviders\Authentik\AuthentikExtendSocialite::class.'@handle',
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Laravel\Socialite\Facades\Socialite;
|
||||
use SocialiteProviders\Authentik\Provider;
|
||||
|
||||
class SocialiteServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Register services.
|
||||
*/
|
||||
public function register(): void
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Bootstrap services.
|
||||
*/
|
||||
public function boot(): void
|
||||
{
|
||||
Socialite::extend('authentik', function ($app) {
|
||||
$config = $app['config']['services.authentik'];
|
||||
return Socialite::buildProvider(Provider::class, $config);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -47,6 +47,8 @@
|
||||
"rinvex/countries": "^8.1",
|
||||
"sabre/dav": "^4.0",
|
||||
"sentry/sentry-laravel": "^2.0",
|
||||
"socialiteproviders/authentik": "^5.2.0",
|
||||
"socialiteproviders/manager": "^4.8.1",
|
||||
"spatie/macroable": "^2.0",
|
||||
"stevebauman/location": "^6.1",
|
||||
"symfony/http-client": "^6.0",
|
||||
|
||||
Generated
+129
-5
@@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "cf135499df1575ba5a5747a5fcf4289c",
|
||||
"content-hash": "08b68a4ecc65c514bc69610bc708dfef",
|
||||
"packages": [
|
||||
{
|
||||
"name": "asbiin/laravel-adorable",
|
||||
@@ -8601,6 +8601,130 @@
|
||||
],
|
||||
"time": "2022-10-13T09:21:29+00:00"
|
||||
},
|
||||
{
|
||||
"name": "socialiteproviders/authentik",
|
||||
"version": "5.2.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/SocialiteProviders/Authentik.git",
|
||||
"reference": "4cf129cf04728a38e0531c54454464b162f0fa66"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/SocialiteProviders/Authentik/zipball/4cf129cf04728a38e0531c54454464b162f0fa66",
|
||||
"reference": "4cf129cf04728a38e0531c54454464b162f0fa66",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-json": "*",
|
||||
"php": "^8.0",
|
||||
"socialiteproviders/manager": "^4.4"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"SocialiteProviders\\Authentik\\": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "rf152",
|
||||
"email": "git@rf152.co.uk"
|
||||
}
|
||||
],
|
||||
"description": "Authentik OAuth2 Provider for Laravel Socialite",
|
||||
"keywords": [
|
||||
"authentik",
|
||||
"laravel",
|
||||
"oauth",
|
||||
"provider",
|
||||
"socialite"
|
||||
],
|
||||
"support": {
|
||||
"docs": "https://socialiteproviders.com/authentik",
|
||||
"issues": "https://github.com/socialiteproviders/providers/issues",
|
||||
"source": "https://github.com/socialiteproviders/providers"
|
||||
},
|
||||
"time": "2023-11-07T22:21:16+00:00"
|
||||
},
|
||||
{
|
||||
"name": "socialiteproviders/manager",
|
||||
"version": "v4.8.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/SocialiteProviders/Manager.git",
|
||||
"reference": "8180ec14bef230ec2351cff993d5d2d7ca470ef4"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/SocialiteProviders/Manager/zipball/8180ec14bef230ec2351cff993d5d2d7ca470ef4",
|
||||
"reference": "8180ec14bef230ec2351cff993d5d2d7ca470ef4",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"illuminate/support": "^8.0 || ^9.0 || ^10.0 || ^11.0 || ^12.0",
|
||||
"laravel/socialite": "^5.5",
|
||||
"php": "^8.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"mockery/mockery": "^1.2",
|
||||
"phpunit/phpunit": "^9.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"laravel": {
|
||||
"providers": [
|
||||
"SocialiteProviders\\Manager\\ServiceProvider"
|
||||
]
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"SocialiteProviders\\Manager\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Andy Wendt",
|
||||
"email": "andy@awendt.com"
|
||||
},
|
||||
{
|
||||
"name": "Anton Komarev",
|
||||
"email": "a.komarev@cybercog.su"
|
||||
},
|
||||
{
|
||||
"name": "Miguel Piedrafita",
|
||||
"email": "soy@miguelpiedrafita.com"
|
||||
},
|
||||
{
|
||||
"name": "atymic",
|
||||
"email": "atymicq@gmail.com",
|
||||
"homepage": "https://atymic.dev"
|
||||
}
|
||||
],
|
||||
"description": "Easily add new or override built-in providers in Laravel Socialite.",
|
||||
"homepage": "https://socialiteproviders.com",
|
||||
"keywords": [
|
||||
"laravel",
|
||||
"manager",
|
||||
"oauth",
|
||||
"providers",
|
||||
"socialite"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/socialiteproviders/manager/issues",
|
||||
"source": "https://github.com/socialiteproviders/manager"
|
||||
},
|
||||
"time": "2025-02-24T19:33:30+00:00"
|
||||
},
|
||||
{
|
||||
"name": "spatie/macroable",
|
||||
"version": "2.0.0",
|
||||
@@ -19666,8 +19790,8 @@
|
||||
"aliases": [],
|
||||
"minimum-stability": "stable",
|
||||
"stability-flags": {
|
||||
"werk365/etagconditionals": 20,
|
||||
"roave/security-advisories": 20
|
||||
"roave/security-advisories": 20,
|
||||
"werk365/etagconditionals": 20
|
||||
},
|
||||
"prefer-stable": false,
|
||||
"prefer-lowest": false,
|
||||
@@ -19679,6 +19803,6 @@
|
||||
"ext-intl": "*",
|
||||
"ext-redis": "*"
|
||||
},
|
||||
"platform-dev": [],
|
||||
"plugin-api-version": "2.2.0"
|
||||
"platform-dev": {},
|
||||
"plugin-api-version": "2.6.0"
|
||||
}
|
||||
|
||||
@@ -199,6 +199,7 @@ return [
|
||||
Vluzrmos\LanguageDetector\Providers\LanguageDetectorServiceProvider::class,
|
||||
App\Providers\RouteServiceProvider::class,
|
||||
Laravel\Socialite\SocialiteServiceProvider::class,
|
||||
\SocialiteProviders\Manager\ServiceProvider::class,
|
||||
Intervention\Image\ImageServiceProvider::class,
|
||||
Laravel\Cashier\CashierServiceProvider::class,
|
||||
Laravel\Passport\PassportServiceProvider::class,
|
||||
|
||||
@@ -40,4 +40,11 @@ return [
|
||||
],
|
||||
],
|
||||
|
||||
'authentik' => [
|
||||
'base_url' => env('AUTHENTIK_BASE_URL'),
|
||||
'client_id' => env('AUTHENTIK_CLIENT_ID'),
|
||||
'client_secret' => env('AUTHENTIK_CLIENT_SECRET'),
|
||||
'redirect' => env('AUTHENTIK_REDIRECT_URI')
|
||||
],
|
||||
|
||||
];
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AddOidcFieldsToUsersTable extends Migration
|
||||
{
|
||||
public function up()
|
||||
{
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->string('oidc_sub')->nullable()->index()->comment('OIDC Subject ID from provider');
|
||||
$table->string('oidc_provider')->nullable()->comment('OIDC Provider name (e.g., authentik)');
|
||||
});
|
||||
}
|
||||
|
||||
public function down()
|
||||
{
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->dropColumn(['oidc_sub', 'oidc_provider']);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -24,10 +24,10 @@ services:
|
||||
- ./database:/var/www/html/database
|
||||
- ./resources:/var/www/html/resources
|
||||
- ./routes:/var/www/html/routes
|
||||
- ./config:/var/www/html/config
|
||||
|
||||
mysql:
|
||||
image: mysql:8
|
||||
command: --default-authentication-plugin=mysql_native_password
|
||||
environment:
|
||||
- MYSQL_ROOT_PASSWORD=sekret_root_password
|
||||
- MYSQL_DATABASE=monica
|
||||
|
||||
@@ -45,9 +45,13 @@ return [
|
||||
'password_forget' => 'Forget your password?',
|
||||
'password_reset' => 'Reset your password',
|
||||
'use_recovery' => 'Or you can use a <a href=":url">recovery code</a>',
|
||||
'signup_no_account' => 'Don’t have an account?',
|
||||
'signup_no_account' => 'Don\'t have an account?',
|
||||
'signup' => 'Sign up',
|
||||
'create_account' => 'Create the first account by <a href=":url">signing up</a>',
|
||||
|
||||
'or' => 'or',
|
||||
'login_with_oidc' => 'Login with Single Sign-On',
|
||||
|
||||
'change_language_title' => 'Change language:',
|
||||
'change_language' => 'Change language to :lang',
|
||||
|
||||
|
||||
@@ -57,6 +57,20 @@
|
||||
</label>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
@if(config('services.authentik.base_url'))
|
||||
<div class="mt-4 mb-4 text-center">
|
||||
<div class="divider">
|
||||
<span class="divider-text">{{ trans('auth.or') }}</span>
|
||||
</div>
|
||||
<a href="{{ route('auth.oidc.redirect') }}" class="btn btn-outline-secondary btn-block mt-3">
|
||||
<i class="fa fa-sign-in-alt"></i> {{ trans('auth.login_with_oidc') }}
|
||||
</a>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<form style="display: none;">
|
||||
<div class="form-group links">
|
||||
<ul>
|
||||
<li>{{ trans('auth.password_forget') }} <a href="{{ route('password.request') }}">{{ trans('auth.password_reset') }}</a></li>
|
||||
|
||||
@@ -20,6 +20,10 @@ Route::get('/', 'Auth\LoginController@showLoginOrRegister')->name('loginRedirect
|
||||
|
||||
Auth::routes(['verify' => true]);
|
||||
|
||||
// OIDC Authentication routes
|
||||
Route::get('/auth/authentik', 'Auth\OIDCController@redirectToProvider')->name('auth.oidc.redirect');
|
||||
Route::get('/auth/authentik/callback', 'Auth\OIDCController@handleProviderCallback')->name('auth.oidc.callback');
|
||||
|
||||
// Redirect .well-known urls (https://en.wikipedia.org/wiki/List_of_/.well-known/_services_offered_by_webservers)
|
||||
Route::permanentRedirect('/.well-known/carddav', '/dav/');
|
||||
Route::permanentRedirect('/.well-known/caldav', '/dav/');
|
||||
|
||||
+35
-11
@@ -6,7 +6,7 @@
|
||||
### This file is based off of the `apache` variant in the above mentioned repo
|
||||
###
|
||||
|
||||
FROM php:8.1-apache
|
||||
FROM php:8.2-apache
|
||||
|
||||
# opencontainers annotations https://github.com/opencontainers/image-spec/blob/master/annotations.md
|
||||
LABEL org.opencontainers.image.authors="Alexis Saettler <alexis@saettler.org>" \
|
||||
@@ -75,14 +75,23 @@ RUN set -ex; \
|
||||
# reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies
|
||||
apt-mark auto '.*' > /dev/null; \
|
||||
apt-mark manual $savedAptMark; \
|
||||
\
|
||||
# find and mark runtime dependencies as manual to prevent their removal
|
||||
runDeps="$( \
|
||||
ldd "$(php -r 'echo ini_get("extension_dir");')"/*.so \
|
||||
| awk '/=>/ { print $3 }' \
|
||||
| sort -u \
|
||||
| xargs -r dpkg-query -S \
|
||||
| cut -d: -f1 \
|
||||
| sort -u \
|
||||
| xargs -rt apt-mark manual; \
|
||||
\
|
||||
| awk '/=>/ { print $3 }' \
|
||||
| sort -u \
|
||||
| xargs -r dpkg-query -S 2>/dev/null \
|
||||
| cut -d: -f1 \
|
||||
| sort -u \
|
||||
)"; \
|
||||
if [ -n "$runDeps" ]; then \
|
||||
apt-mark manual $runDeps; \
|
||||
fi; \
|
||||
\
|
||||
# determine current library versions and mark them manual
|
||||
apt list --installed | grep -E "lib(png|icu|zip|memcached|freetype|jpeg|webp|gmp|xml|magick)" | cut -d/ -f1 | xargs -r apt-mark manual 2>/dev/null || true; \
|
||||
\
|
||||
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
@@ -150,8 +159,17 @@ RUN set -ex; \
|
||||
COPY --chown=www-data:www-data .env.example .env
|
||||
|
||||
# Composer installation
|
||||
COPY scripts/docker/install-composer.sh /usr/local/sbin/
|
||||
RUN install-composer.sh
|
||||
RUN set -ex; \
|
||||
EXPECTED_SIGNATURE=$(curl -sS https://composer.github.io/installer.sig); \
|
||||
curl -sS -o composer-setup.php https://getcomposer.org/installer; \
|
||||
ACTUAL_SIGNATURE=$(openssl sha384 composer-setup.php | cut -d' ' -f2); \
|
||||
if [ "$EXPECTED_SIGNATURE" != "$ACTUAL_SIGNATURE" ]; then \
|
||||
>&2 echo 'ERROR: Invalid installer signature'; \
|
||||
rm composer-setup.php; \
|
||||
exit 1; \
|
||||
fi; \
|
||||
php composer-setup.php --quiet --install-dir=/usr/local/bin --filename=composer; \
|
||||
rm composer-setup.php
|
||||
|
||||
# Install composer dependencies
|
||||
RUN set -ex; \
|
||||
@@ -164,7 +182,7 @@ RUN set -ex; \
|
||||
# Install node dependencies
|
||||
RUN set -ex; \
|
||||
\
|
||||
curl -fsSL https://deb.nodesource.com/setup_18.x | bash -; \
|
||||
curl -fsSL https://deb.nodesource.com/setup_20.x | bash -; \
|
||||
apt-get install -y nodejs; \
|
||||
npm install -g yarn; \
|
||||
yarn run inst; \
|
||||
@@ -177,5 +195,11 @@ COPY scripts/docker/entrypoint.sh \
|
||||
scripts/docker/queue.sh \
|
||||
/usr/local/bin/
|
||||
|
||||
# Fix Windows line endings and make scripts executable
|
||||
RUN apt-get update && apt-get install -y dos2unix && \
|
||||
dos2unix /usr/local/bin/entrypoint.sh /usr/local/bin/cron.sh /usr/local/bin/queue.sh && \
|
||||
chmod +x /usr/local/bin/entrypoint.sh /usr/local/bin/cron.sh /usr/local/bin/queue.sh && \
|
||||
apt-get purge -y dos2unix && apt-get autoremove -y && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ENTRYPOINT ["entrypoint.sh"]
|
||||
CMD ["apache2-foreground"]
|
||||
|
||||
Reference in New Issue
Block a user