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

View File

@ -1,23 +1,23 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="GameyfinApplication" type="SpringBootApplicationConfigurationType"
factoryName="Spring Boot" nameIsGenerated="true">
<option name="ACTIVE_PROFILES" value="dev"/>
<option name="ALTERNATIVE_JRE_PATH" value="BUNDLED"/>
<envs>
<env name="APP_KEY" value="8ODYedBBEA6qTd2Z/dZiWA=="/>
</envs>
<module name="Gameyfin.app.main"/>
<option name="SHORTEN_COMMAND_LINE" value="ARGS_FILE"/>
<option name="SPRING_BOOT_MAIN_CLASS" value="org.gameyfin.app.GameyfinApplication"/>
<option name="VM_PARAMETERS" value="-Dpf4j.mode=development"/>
<extension name="coverage">
<pattern>
<option name="PATTERN" value="org.gameyfin.app.*"/>
<option name="ENABLED" value="true"/>
</pattern>
</extension>
<method v="2">
<option name="Make" enabled="true"/>
</method>
</configuration>
<configuration default="false" name="GameyfinApplication" type="SpringBootApplicationConfigurationType" factoryName="Spring Boot" nameIsGenerated="true">
<option name="ACTIVE_PROFILES" value="dev" />
<option name="ALTERNATIVE_JRE_PATH" value="BUNDLED" />
<envs>
<env name="APP_KEY" value="8ODYedBBEA6qTd2Z/dZiWA==" />
<env name="APP_URL" value="http://test.gameyfin.org" />
</envs>
<module name="Gameyfin.app.main" />
<option name="SHORTEN_COMMAND_LINE" value="ARGS_FILE" />
<option name="SPRING_BOOT_MAIN_CLASS" value="org.gameyfin.app.GameyfinApplication" />
<option name="VM_PARAMETERS" value="-Dpf4j.mode=development" />
<extension name="coverage">
<pattern>
<option name="PATTERN" value="org.gameyfin.app.*" />
<option name="ENABLED" value="true" />
</pattern>
</extension>
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
</component>

View File

@ -2,7 +2,7 @@
<configuration default="false" name="Production build" type="GradleRunConfiguration" factoryName="Gradle">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$/app" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="-Pvaadin.productionMode=true" />
<option name="taskDescriptions">

View File

@ -1,6 +1,6 @@
{
"name": "gameyfin",
"version": "2.0.0.beta2",
"version": "2.0.0.beta3",
"type": "module",
"dependencies": {
"@heroui/react": "2.7.9",

Binary file not shown.

View File

@ -263,7 +263,7 @@ sealed class ConfigProperties<T : Serializable>(
data object AllowedOrigins : ConfigProperties<Array<String>>(
Array<String>::class,
"system.cors.allowed-origins",
"List of allowed CORS origins",
"List of allowed CORS origins (currently unused)",
emptyArray()
)
}

View File

@ -1,8 +1,8 @@
package org.gameyfin.app.core
import io.github.oshai.kotlinlogging.KotlinLogging
import org.gameyfin.app.setup.SetupService
import org.gameyfin.app.users.UserService
import io.github.oshai.kotlinlogging.KotlinLogging
import org.gameyfin.app.users.entities.User
import org.springframework.boot.context.event.ApplicationReadyEvent
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"
log.info { "Visit $protocol://${InetAddress.getLocalHost().hostName}:${env.getProperty("server.port")}/setup to complete the setup" }
val rawAppUrl = env.getProperty("app.url")
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() {

View File

@ -1,8 +1,8 @@
package org.gameyfin.app.core.security
import com.vaadin.flow.spring.security.VaadinWebSecurity
import org.gameyfin.app.config.ConfigService
import org.gameyfin.app.config.ConfigProperties
import org.gameyfin.app.config.ConfigService
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Conditional
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.core.AuthorizationGrantType
import org.springframework.security.web.authentication.logout.HttpStatusReturningLogoutSuccessHandler
import org.springframework.web.cors.CorsConfiguration
@Configuration
@ -53,13 +52,8 @@ class SecurityConfig(
.sessionRegistry(sessionRegistry)
}
http.cors { cors ->
cors.configurationSource { request ->
val configuration = CorsConfiguration()
configuration.allowedOrigins = allowedOrigins
configuration
}
}
// Not needed since the frontend is served by the backend
http.cors { cors -> cors.disable() }
super.configure(http)

View File

@ -6,7 +6,7 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile
import java.nio.file.Files
group = "org.gameyfin"
version = "2.0.0.beta2"
version = "2.0.0.beta3"
allprojects {
repositories {
@ -22,6 +22,10 @@ plugins {
kotlin("jvm")
}
tasks.named<Jar>("jar") {
enabled = false
}
subprojects {
apply(plugin = "java")

View File

@ -1,26 +1,36 @@
# syntax=docker/dockerfile:1.4
FROM eclipse-temurin:21-jre-alpine
MAINTAINER grimsi
# Install necessary packages
RUN apk add --no-cache su-exec tini shadow
ENV USER=gameyfin
RUN addgroup gameyfin && \
adduser --disabled-password --gecos "" --ingroup "$USER" --no-create-home "$USER"
USER gameyfin: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 --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
# Copy all plugin jars
COPY --chown=gameyfin:gameyfin ./plugins/ /tmp/plugins/
RUN mkdir -p /opt/gameyfin/plugins && \
find /tmp/plugins -type f -path "*/build/libs/*.jar" -exec cp {} /opt/gameyfin/plugins/ \; && \
RUN find /tmp/plugins -type f -path "*/build/libs/*.jar" -exec cp {} plugins/ \; && \
rm -rf /tmp/plugins
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "gameyfin.jar"]
ENTRYPOINT ["/sbin/tini", "--", "/entrypoint.sh"]

11
docker/entrypoint.sh Normal file
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
docker/how-to-build.txt Normal file
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.

View File

@ -4,13 +4,19 @@ plugins {
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 keystoreAlias = "gameyfin-plugins"
val keystorePassword: String = (findProperty("keystorePassword") as String?)
?: System.getenv("GAMEYFIN_KEYSTORE_PASSWORD")
val keystorePassword: String = (findProperty(keystorePasswordProperty) as String?)
?: System.getenv(keystorePasswordEnvironmentVariable)
?: ""
subprojects {
apply(plugin = "org.jetbrains.kotlin.jvm")
@ -67,6 +73,11 @@ subprojects {
tasks.register<Exec>("signJar") {
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
// Only enable if password is present