Update to 2.0.0.beta3

Added entrypoint to Docker image
Fixed issues with CORS when behind reverse-proxy
Added APP_URL environment variable
This commit is contained in:
GRIMSIM
2025-06-17 17:27:42 +02:00
parent f8e69e6b49
commit 373fbba63c
12 changed files with 86 additions and 46 deletions
+21 -21
View File
@@ -1,23 +1,23 @@
<component name="ProjectRunConfigurationManager"> <component name="ProjectRunConfigurationManager">
<configuration default="false" name="GameyfinApplication" type="SpringBootApplicationConfigurationType" <configuration default="false" name="GameyfinApplication" type="SpringBootApplicationConfigurationType" factoryName="Spring Boot" nameIsGenerated="true">
factoryName="Spring Boot" nameIsGenerated="true"> <option name="ACTIVE_PROFILES" value="dev" />
<option name="ACTIVE_PROFILES" value="dev"/> <option name="ALTERNATIVE_JRE_PATH" value="BUNDLED" />
<option name="ALTERNATIVE_JRE_PATH" value="BUNDLED"/> <envs>
<envs> <env name="APP_KEY" value="8ODYedBBEA6qTd2Z/dZiWA==" />
<env name="APP_KEY" value="8ODYedBBEA6qTd2Z/dZiWA=="/> <env name="APP_URL" value="http://test.gameyfin.org" />
</envs> </envs>
<module name="Gameyfin.app.main"/> <module name="Gameyfin.app.main" />
<option name="SHORTEN_COMMAND_LINE" value="ARGS_FILE"/> <option name="SHORTEN_COMMAND_LINE" value="ARGS_FILE" />
<option name="SPRING_BOOT_MAIN_CLASS" value="org.gameyfin.app.GameyfinApplication"/> <option name="SPRING_BOOT_MAIN_CLASS" value="org.gameyfin.app.GameyfinApplication" />
<option name="VM_PARAMETERS" value="-Dpf4j.mode=development"/> <option name="VM_PARAMETERS" value="-Dpf4j.mode=development" />
<extension name="coverage"> <extension name="coverage">
<pattern> <pattern>
<option name="PATTERN" value="org.gameyfin.app.*"/> <option name="PATTERN" value="org.gameyfin.app.*" />
<option name="ENABLED" value="true"/> <option name="ENABLED" value="true" />
</pattern> </pattern>
</extension> </extension>
<method v="2"> <method v="2">
<option name="Make" enabled="true"/> <option name="Make" enabled="true" />
</method> </method>
</configuration> </configuration>
</component> </component>
+1 -1
View File
@@ -2,7 +2,7 @@
<configuration default="false" name="Production build" type="GradleRunConfiguration" factoryName="Gradle"> <configuration default="false" name="Production build" type="GradleRunConfiguration" factoryName="Gradle">
<ExternalSystemSettings> <ExternalSystemSettings>
<option name="executionName" /> <option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$/app" /> <option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" /> <option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="-Pvaadin.productionMode=true" /> <option name="scriptParameters" value="-Pvaadin.productionMode=true" />
<option name="taskDescriptions"> <option name="taskDescriptions">
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "gameyfin", "name": "gameyfin",
"version": "2.0.0.beta2", "version": "2.0.0.beta3",
"type": "module", "type": "module",
"dependencies": { "dependencies": {
"@heroui/react": "2.7.9", "@heroui/react": "2.7.9",
Binary file not shown.
@@ -263,7 +263,7 @@ sealed class ConfigProperties<T : Serializable>(
data object AllowedOrigins : ConfigProperties<Array<String>>( data object AllowedOrigins : ConfigProperties<Array<String>>(
Array<String>::class, Array<String>::class,
"system.cors.allowed-origins", "system.cors.allowed-origins",
"List of allowed CORS origins", "List of allowed CORS origins (currently unused)",
emptyArray() emptyArray()
) )
} }
@@ -1,8 +1,8 @@
package org.gameyfin.app.core package org.gameyfin.app.core
import io.github.oshai.kotlinlogging.KotlinLogging
import org.gameyfin.app.setup.SetupService import org.gameyfin.app.setup.SetupService
import org.gameyfin.app.users.UserService import org.gameyfin.app.users.UserService
import io.github.oshai.kotlinlogging.KotlinLogging
import org.gameyfin.app.users.entities.User import org.gameyfin.app.users.entities.User
import org.springframework.boot.context.event.ApplicationReadyEvent import org.springframework.boot.context.event.ApplicationReadyEvent
import org.springframework.context.event.EventListener import org.springframework.context.event.EventListener
@@ -32,8 +32,15 @@ class SetupDataLoader(
} }
val protocol = if (env.getProperty("server.ssl.key-store") != null) "https" else "http" val protocol = if (env.getProperty("server.ssl.key-store") != null) "https" else "http"
val rawAppUrl = env.getProperty("app.url")
log.info { "Visit $protocol://${InetAddress.getLocalHost().hostName}:${env.getProperty("server.port")}/setup to complete the setup" } val appUrl = when {
rawAppUrl.isNullOrBlank() -> null
rawAppUrl.startsWith("http://") || rawAppUrl.startsWith("https://") -> rawAppUrl
else -> "$protocol://$rawAppUrl"
}
val setupUrl =
appUrl ?: "${protocol}://${InetAddress.getLocalHost().hostName}:${env.getProperty("server.port")}/setup"
log.info { "Visit $setupUrl to complete the setup" }
} }
fun setupUsers() { fun setupUsers() {
@@ -1,8 +1,8 @@
package org.gameyfin.app.core.security package org.gameyfin.app.core.security
import com.vaadin.flow.spring.security.VaadinWebSecurity import com.vaadin.flow.spring.security.VaadinWebSecurity
import org.gameyfin.app.config.ConfigService
import org.gameyfin.app.config.ConfigProperties import org.gameyfin.app.config.ConfigProperties
import org.gameyfin.app.config.ConfigService
import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Conditional import org.springframework.context.annotation.Conditional
import org.springframework.context.annotation.Configuration import org.springframework.context.annotation.Configuration
@@ -19,7 +19,6 @@ import org.springframework.security.oauth2.client.registration.ClientRegistratio
import org.springframework.security.oauth2.client.registration.InMemoryClientRegistrationRepository import org.springframework.security.oauth2.client.registration.InMemoryClientRegistrationRepository
import org.springframework.security.oauth2.core.AuthorizationGrantType import org.springframework.security.oauth2.core.AuthorizationGrantType
import org.springframework.security.web.authentication.logout.HttpStatusReturningLogoutSuccessHandler import org.springframework.security.web.authentication.logout.HttpStatusReturningLogoutSuccessHandler
import org.springframework.web.cors.CorsConfiguration
@Configuration @Configuration
@@ -53,13 +52,8 @@ class SecurityConfig(
.sessionRegistry(sessionRegistry) .sessionRegistry(sessionRegistry)
} }
http.cors { cors -> // Not needed since the frontend is served by the backend
cors.configurationSource { request -> http.cors { cors -> cors.disable() }
val configuration = CorsConfiguration()
configuration.allowedOrigins = allowedOrigins
configuration
}
}
super.configure(http) super.configure(http)
+5 -1
View File
@@ -6,7 +6,7 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile
import java.nio.file.Files import java.nio.file.Files
group = "org.gameyfin" group = "org.gameyfin"
version = "2.0.0.beta2" version = "2.0.0.beta3"
allprojects { allprojects {
repositories { repositories {
@@ -22,6 +22,10 @@ plugins {
kotlin("jvm") kotlin("jvm")
} }
tasks.named<Jar>("jar") {
enabled = false
}
subprojects { subprojects {
apply(plugin = "java") apply(plugin = "java")
+16 -6
View File
@@ -1,26 +1,36 @@
# syntax=docker/dockerfile:1.4 # syntax=docker/dockerfile:1.4
FROM eclipse-temurin:21-jre-alpine FROM eclipse-temurin:21-jre-alpine
MAINTAINER grimsi
# Install necessary packages
RUN apk add --no-cache su-exec tini shadow
ENV USER=gameyfin ENV USER=gameyfin
RUN addgroup gameyfin && \ RUN addgroup gameyfin && \
adduser --disabled-password --gecos "" --ingroup "$USER" --no-create-home "$USER" adduser --disabled-password --gecos "" --ingroup "$USER" --no-create-home "$USER"
USER gameyfin:gameyfin
WORKDIR /opt/gameyfin WORKDIR /opt/gameyfin
# Create necessary directories with appropriate permissions
RUN mkdir -p plugins db data logs && \
chown -R gameyfin:gameyfin .
# Copy entrypoint script and set permissions
COPY --chown=gameyfin:gameyfin ./docker/entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
# Copy application jar (not ending with -plain.jar) # Copy application jar (not ending with -plain.jar)
COPY --chown=gameyfin:gameyfin ./app/build/libs/ /tmp/app-libs/ COPY --chown=gameyfin:gameyfin ./app/build/libs/ /tmp/app-libs/
RUN find /tmp/app-libs -type f -name "*.jar" ! -name "*-plain.jar" -exec cp {} /opt/gameyfin/gameyfin.jar \; && \ RUN find /tmp/app-libs -type f -name "*.jar" ! -name "*-plain.jar" -exec cp {} gameyfin.jar \; && \
rm -rf /tmp/app-libs rm -rf /tmp/app-libs
# Copy all plugin jars # Copy all plugin jars
COPY --chown=gameyfin:gameyfin ./plugins/ /tmp/plugins/ COPY --chown=gameyfin:gameyfin ./plugins/ /tmp/plugins/
RUN mkdir -p /opt/gameyfin/plugins && \ RUN find /tmp/plugins -type f -path "*/build/libs/*.jar" -exec cp {} plugins/ \; && \
find /tmp/plugins -type f -path "*/build/libs/*.jar" -exec cp {} /opt/gameyfin/plugins/ \; && \
rm -rf /tmp/plugins rm -rf /tmp/plugins
EXPOSE 8080 EXPOSE 8080
ENTRYPOINT ["java", "-jar", "gameyfin.jar"] ENTRYPOINT ["/sbin/tini", "--", "/entrypoint.sh"]
+11
View File
@@ -0,0 +1,11 @@
#!/bin/sh
set -e
if [ -n "$PUID" ] && [ -n "$PGID" ]; then
groupmod -o -g "$PGID" gameyfin
usermod -o -u "$PUID" gameyfin
chown -R gameyfin:gameyfin /opt/gameyfin
exec su-exec gameyfin:gameyfin java -jar gameyfin.jar
else
exec su-exec gameyfin:gameyfin java -jar gameyfin.jar
fi
+3
View File
@@ -0,0 +1,3 @@
1. Run production build
2. Run docker build in root dir: docker buildx build --platform linux/arm64/v8,linux/amd64 -f docker/Dockerfile --tag grimsi/gameyfin:<TAG> .
2.1 If you want to push the image to a registry, add --push to the command above.
+14 -3
View File
@@ -4,13 +4,19 @@ plugins {
kotlin("jvm") kotlin("jvm")
} }
tasks.named<Jar>("jar") {
enabled = false
}
val keystorePasswordEnvironmentVariable = "GAMEYFIN_KEYSTORE_PASSWORD"
val keystorePasswordProperty = "gameyfin.keystorePassword"
val keystorePath: String = rootProject.file("certs/gameyfin.jks").absolutePath val keystorePath: String = rootProject.file("certs/gameyfin.jks").absolutePath
val keystoreAlias = "gameyfin-plugins" val keystoreAlias = "gameyfin-plugins"
val keystorePassword: String = (findProperty("keystorePassword") as String?) val keystorePassword: String = (findProperty(keystorePasswordProperty) as String?)
?: System.getenv("GAMEYFIN_KEYSTORE_PASSWORD") ?: System.getenv(keystorePasswordEnvironmentVariable)
?: "" ?: ""
subprojects { subprojects {
apply(plugin = "org.jetbrains.kotlin.jvm") apply(plugin = "org.jetbrains.kotlin.jvm")
@@ -67,6 +73,11 @@ subprojects {
tasks.register<Exec>("signJar") { tasks.register<Exec>("signJar") {
dependsOn(tasks.jar) dependsOn(tasks.jar)
if ((findProperty("vaadin.productionMode") as String?) == "true" && keystorePassword.isEmpty()) {
throw GradleException("Keystore password must be provided when vaadin.productionMode is true. Use -P$keystorePasswordProperty=your_password or set the $keystorePasswordEnvironmentVariable environment variable.")
}
val jarFile = tasks.jar.get().archiveFile.get().asFile val jarFile = tasks.jar.get().archiveFile.get().asFile
// Only enable if password is present // Only enable if password is present