The update endpoint ran the entire git pull + docker build (up to 10 min) synchronously inside the request handler, blocking the whole server for everyone while it ran. Separately, the frontend spinner was only hidden on error, never on success, so it spun forever even when the update worked. - Run the update in a background thread; the request returns immediately - Add GET /settings/update/status for progress polling (backup/pull/build/restart) - Frontend polls status, then waits for the app to come back after the container restart, and shows a clear done/timeout message instead of an endless spinner Co-Authored-By: Claude Sonnet 5 <[email protected]>
425 lines
18 KiB
JSON
425 lines
18 KiB
JSON
{
|
|
"login": {
|
|
"subtitle": "Multi-Tenant Management Platform",
|
|
"username": "Username",
|
|
"password": "Password",
|
|
"signIn": "Sign In",
|
|
"signInWithMicrosoft": "Sign in with Microsoft"
|
|
},
|
|
"nav": {
|
|
"newCustomer": "New Customer",
|
|
"settings": "Settings",
|
|
"monitoring": "Monitoring",
|
|
"logout": "Logout"
|
|
},
|
|
"dashboard": {
|
|
"totalCustomers": "Total Customers",
|
|
"active": "Active",
|
|
"inactive": "Inactive",
|
|
"errors": "Errors",
|
|
"searchPlaceholder": "Search by name, subdomain, email...",
|
|
"allStatuses": "All Statuses",
|
|
"statusActive": "Active",
|
|
"statusInactive": "Inactive",
|
|
"statusDeploying": "Deploying",
|
|
"statusError": "Error",
|
|
"refresh": "Refresh",
|
|
"thId": "ID",
|
|
"thName": "Name",
|
|
"thSubdomain": "Subdomain",
|
|
"thStatus": "Status",
|
|
"thDashboard": "Dashboard",
|
|
"thDevices": "Devices",
|
|
"thCreated": "Created",
|
|
"thActions": "Actions",
|
|
"noCustomers": "No customers found. Click \"New Customer\" to create one.",
|
|
"showing": "Showing {start}-{end} of {total}",
|
|
"showingEmpty": "Showing 0 of 0"
|
|
},
|
|
"customer": {
|
|
"back": "Back",
|
|
"customer": "Customer",
|
|
"edit": "Edit",
|
|
"delete": "Delete",
|
|
"tabInfo": "Info",
|
|
"tabDeployment": "Deployment",
|
|
"tabLogs": "Logs",
|
|
"tabHealth": "Health",
|
|
"name": "Name:",
|
|
"company": "Company:",
|
|
"subdomain": "Subdomain:",
|
|
"email": "Email:",
|
|
"maxDevices": "Max Devices:",
|
|
"status": "Status:",
|
|
"created": "Created:",
|
|
"updated": "Updated:",
|
|
"notes": "Notes:",
|
|
"deploymentStatus": "Status:",
|
|
"relayUdpPort": "Relay UDP Port:",
|
|
"dashboardPort": "Dashboard Port:",
|
|
"containerPrefix": "Container Prefix:",
|
|
"deployed": "Deployed:",
|
|
"setupUrl": "Setup URL:",
|
|
"copy": "Copy",
|
|
"open": "Open",
|
|
"netbirdLogin": "NetBird Login",
|
|
"notAvailable": "Not available",
|
|
"showCredentials": "Show Credentials",
|
|
"credEmail": "Email",
|
|
"credPassword": "Password",
|
|
"showHide": "Show/Hide",
|
|
"credentialsNotAvailable": "Credentials not available. Admin must complete setup manually at the Setup URL.",
|
|
"start": "Start",
|
|
"stop": "Stop",
|
|
"restart": "Restart",
|
|
"reDeploy": "Re-Deploy",
|
|
"noDeployment": "No deployment found.",
|
|
"deployNow": "Deploy Now",
|
|
"containerLogs": "Container Logs",
|
|
"noContainerLogs": "No container logs available.",
|
|
"noLogsLoaded": "No logs loaded.",
|
|
"healthCheck": "Health Check",
|
|
"check": "Check",
|
|
"clickCheck": "Click \"Check\" to run a health check.",
|
|
"healthy": "Healthy",
|
|
"unhealthy": "Unhealthy",
|
|
"overall": "Overall:",
|
|
"thContainer": "Container",
|
|
"thContainerStatus": "Status",
|
|
"thHealth": "Health",
|
|
"thImage": "Image",
|
|
"lastCheck": "Last check: {time}",
|
|
"openDashboard": "Open Dashboard",
|
|
"updateImages": "Update Images",
|
|
"updateInProgress": "Updating containers — please wait…"
|
|
},
|
|
"customerModal": {
|
|
"newCustomer": "New Customer",
|
|
"editCustomer": "Edit Customer",
|
|
"nameLabel": "Name *",
|
|
"companyLabel": "Company",
|
|
"subdomainLabel": "Subdomain *",
|
|
"subdomainHint": "Lowercase, alphanumeric + hyphens",
|
|
"emailLabel": "Email *",
|
|
"maxDevicesLabel": "Max Devices",
|
|
"notesLabel": "Notes",
|
|
"cancel": "Cancel",
|
|
"saveAndDeploy": "Save & Deploy",
|
|
"saveChanges": "Save Changes"
|
|
},
|
|
"redeployModal": {
|
|
"title": "Redeploy Customer",
|
|
"intro": "How should",
|
|
"intro2": "be redeployed?",
|
|
"keepTitle": "Keep Data",
|
|
"keepDesc": "Containers are stopped and restarted. The NetBird database, peer configurations, and encryption keys are preserved. Use this after a config change or image update.",
|
|
"keepNote": "Peers stay connected after restart.",
|
|
"freshTitle": "Fresh Deploy",
|
|
"freshDesc": "All existing data is deleted — containers, volumes, config files, and the NetBird database. A completely new instance is created. All peers must re-enroll.",
|
|
"freshNote": "All peer data is lost. Cannot be undone."
|
|
},
|
|
"deleteModal": {
|
|
"title": "Confirm Deletion",
|
|
"confirmText": "Are you sure you want to delete customer",
|
|
"warning": "This will remove all containers, NPM entries, and data. This action cannot be undone.",
|
|
"cancel": "Cancel",
|
|
"delete": "Delete"
|
|
},
|
|
"settings": {
|
|
"title": "System Settings",
|
|
"tabSystem": "NetBird MSP System",
|
|
"tabNpm": "NPM Proxy",
|
|
"tabImages": "NetBird Docker Images",
|
|
"tabBranding": "Branding",
|
|
"tabUsers": "Users",
|
|
"tabAzure": "Azure AD",
|
|
"tabDns": "Windows DNS",
|
|
"tabLdap": "LDAP / AD",
|
|
"tabUpdate": "NetBird MSP Updates",
|
|
"tabSecurity": "Security",
|
|
"groupUsers": "User Management",
|
|
"groupSystem": "System Configuration",
|
|
"groupExternal": "External Systems",
|
|
"baseDomain": "Base Domain",
|
|
"baseDomainPlaceholder": "yourdomain.com",
|
|
"baseDomainHint": "Customers get subdomains: customer.yourdomain.com",
|
|
"adminEmail": "Admin Email",
|
|
"adminEmailPlaceholder": "[email protected]",
|
|
"dataDir": "Data Directory",
|
|
"dataDirPlaceholder": "/opt/netbird-instances",
|
|
"dockerNetwork": "Docker Network",
|
|
"dockerNetworkPlaceholder": "npm-network",
|
|
"relayBasePort": "Relay Base Port",
|
|
"relayBasePortHint": "First UDP port for relay. Range: base to base+99",
|
|
"dashboardBasePort": "Dashboard Base Port",
|
|
"dashboardBasePortHint": "Base port for customer dashboards. Customer N gets base+N",
|
|
"saveSystemSettings": "Save System Settings",
|
|
"npmDescription": "NPM uses JWT authentication. Enter your NPM login credentials (email + password). The system will automatically log in and obtain tokens for API calls.",
|
|
"npmApiUrl": "NPM API URL",
|
|
"npmApiUrlPlaceholder": "http://nginx-proxy-manager:81/api",
|
|
"npmApiUrlHint": "http:// or https:// - must include /api at the end",
|
|
"npmLoginEmail": "NPM Login Email",
|
|
"npmLoginEmailPlaceholder": "Leave empty to keep current",
|
|
"npmLoginPassword": "NPM Login Password",
|
|
"npmLoginPasswordPlaceholder": "Leave empty to keep current",
|
|
"credentialsSet": "Credentials are set (leave empty to keep current)",
|
|
"noCredentials": "No NPM credentials configured",
|
|
"saveNpmSettings": "Save NPM Settings",
|
|
"testConnection": "Test Connection",
|
|
"sslModeTitle": "SSL Certificate Mode",
|
|
"sslMode": "SSL Mode",
|
|
"sslModeLetsencrypt": "Let's Encrypt (per customer)",
|
|
"sslModeWildcard": "Wildcard Certificate",
|
|
"sslModeHint": "Choose whether each customer gets an individual Let's Encrypt certificate or uses a shared wildcard certificate.",
|
|
"wildcardCertificate": "Wildcard Certificate",
|
|
"selectCertificate": "-- Select certificate --",
|
|
"wildcardCertHint": "Select the wildcard certificate (e.g. *.example.com) already uploaded in NPM.",
|
|
"noWildcardCerts": "No wildcard certificates found in NPM.",
|
|
"certsLoaded": "{count} wildcard certificate(s) found.",
|
|
"expiresOn": "Expires",
|
|
"managementImage": "Management Image",
|
|
"managementImagePlaceholder": "netbirdio/management:latest",
|
|
"signalImage": "Signal Image",
|
|
"signalImagePlaceholder": "netbirdio/signal:latest",
|
|
"relayImage": "Relay Image",
|
|
"relayImagePlaceholder": "netbirdio/relay:latest",
|
|
"dashboardImage": "Dashboard Image",
|
|
"dashboardImagePlaceholder": "netbirdio/dashboard:latest",
|
|
"saveImageSettings": "Save Image Settings",
|
|
"pullImagesTitle": "Pull Latest Images from Docker Hub",
|
|
"pullImagesHint": "Downloads the latest versions of all configured NetBird images. After pulling, use Monitoring to update customer containers.",
|
|
"pullImages": "Pull from Docker Hub",
|
|
"brandingTitle": "Branding Settings",
|
|
"companyName": "Company / Application Name",
|
|
"companyNamePlaceholder": "NetBird MSP Appliance",
|
|
"companyNameHint": "Displayed on login page and navbar",
|
|
"logoPreview": "Logo Preview",
|
|
"defaultIcon": "Default icon (no logo uploaded)",
|
|
"uploadLogo": "Upload Logo (PNG, JPG, SVG, max 500KB)",
|
|
"uploadBtn": "Upload",
|
|
"removeLogo": "Remove Logo",
|
|
"brandingSubtitle": "Subtitle",
|
|
"brandingSubtitlePlaceholder": "Multi-Tenant Management Platform",
|
|
"brandingSubtitleHint": "Shown below the title on the login page",
|
|
"defaultLanguage": "Default Language",
|
|
"defaultLanguageHint": "Default language for users without a preference",
|
|
"systemDefault": "System Default",
|
|
"saveBranding": "Save Branding",
|
|
"userManagement": "User Management",
|
|
"newUser": "New User",
|
|
"makeAdmin": "Promote to admin",
|
|
"makeViewer": "Demote to viewer",
|
|
"thId": "ID",
|
|
"thUsername": "Username",
|
|
"thEmail": "Email",
|
|
"thRole": "Role",
|
|
"thAuth": "Auth",
|
|
"thLanguage": "Language",
|
|
"thStatus": "Status",
|
|
"thActions": "Actions",
|
|
"azureTitle": "Azure AD / Entra ID Integration",
|
|
"enableAzureSso": "Enable Azure AD SSO",
|
|
"tenantId": "Tenant ID",
|
|
"clientId": "Client ID (Application ID)",
|
|
"clientSecret": "Client Secret",
|
|
"clientSecretPlaceholder": "Leave empty to keep current",
|
|
"secretSet": "Secret is set (leave empty to keep current)",
|
|
"noSecret": "No client secret configured",
|
|
"saveAzureSettings": "Save Azure AD Settings",
|
|
"azureGroupId": "Allowed Group Object ID (optional)",
|
|
"azureGroupIdHint": "If set, only Azure AD members of this group can log in.",
|
|
"dnsTitle": "Windows DNS Integration",
|
|
"enableDns": "Enable Windows DNS Integration",
|
|
"dnsDescription": "Automatically create/delete DNS A-records when deploying customers.",
|
|
"dnsServer": "DNS Server Address",
|
|
"dnsZone": "DNS Zone",
|
|
"dnsUsername": "Username (NTLM)",
|
|
"dnsPassword": "Password",
|
|
"dnsRecordIp": "A-Record Target IP",
|
|
"dnsRecordIpHint": "IP address that customer A-records will point to (usually your NPM server IP).",
|
|
"saveDnsSettings": "Save DNS Settings",
|
|
"ldapTitle": "LDAP / Active Directory Authentication",
|
|
"enableLdap": "Enable LDAP / AD Authentication",
|
|
"ldapDescription": "Allow Active Directory users to log in. Local admin accounts always work as fallback.",
|
|
"ldapServer": "LDAP Server",
|
|
"ldapPort": "Port",
|
|
"ldapUseSsl": "Use SSL/TLS (LDAPS)",
|
|
"ldapBindDn": "Bind DN (Service Account)",
|
|
"ldapBindPassword": "Bind Password",
|
|
"ldapBaseDn": "Base DN",
|
|
"ldapUserFilter": "User Filter",
|
|
"ldapUserFilterHint": "Use {username} as placeholder for the login name.",
|
|
"ldapGroupDn": "Group Restriction DN (optional)",
|
|
"ldapGroupDnHint": "If set, only members of this group can log in via LDAP.",
|
|
"saveLdapSettings": "Save LDAP Settings",
|
|
"versionTitle": "Version & Updates",
|
|
"currentVersion": "Installed Version",
|
|
"latestVersion": "Latest Available",
|
|
"branch": "Branch",
|
|
"commitHash": "Commit",
|
|
"updateAvailable": "Update Available",
|
|
"upToDate": "Up to date",
|
|
"triggerUpdate": "Start Update",
|
|
"updateWarning": "The app will be unavailable for ~60 seconds during rebuild.",
|
|
"confirmUpdate": "Start the update now? The database will be backed up first. The app will restart (~60 seconds downtime).",
|
|
"updateStepStarting": "Starting update …",
|
|
"updateStepBackup": "Backing up database …",
|
|
"updateStepPull": "Fetching code …",
|
|
"updateStepBuild": "Building Docker image (can take several minutes) …",
|
|
"updateStepRestart": "Restarting container …",
|
|
"updateStepReconnecting": "Container is restarting — waiting for connection …",
|
|
"updateStepDone": "Update complete.",
|
|
"updateStepTimeout": "Update is taking longer than expected. Check the server logs or reload this page in a few minutes.",
|
|
"gitTitle": "Git Repository Settings",
|
|
"gitRepoUrl": "Repository URL",
|
|
"gitRepoUrlHint": "Used for version checks and one-click updates via Gitea API.",
|
|
"gitBranch": "Branch",
|
|
"gitToken": "Access Token (optional)",
|
|
"saveGitSettings": "Save Git Settings",
|
|
"leaveEmptyToKeep": "Leave empty to keep current",
|
|
"passwordSet": "Password is set (leave empty to keep current)",
|
|
"noPasswordSet": "No password configured",
|
|
"tokenSet": "Token is set (leave empty to keep current)",
|
|
"noToken": "No access token configured",
|
|
"securityTitle": "Change Admin Password",
|
|
"currentPassword": "Current Password",
|
|
"newPassword": "New Password (min 12 chars)",
|
|
"confirmPassword": "Confirm New Password",
|
|
"changePassword": "Change Password"
|
|
},
|
|
"monitoring": {
|
|
"title": "System Monitoring",
|
|
"refresh": "Refresh",
|
|
"hostResources": "Host Resources",
|
|
"hostname": "Hostname",
|
|
"cpu": "CPU ({count} cores)",
|
|
"memory": "Memory ({used}/{total} GB)",
|
|
"disk": "Disk ({used}/{total} GB)",
|
|
"allCustomerDeployments": "All Customer Deployments",
|
|
"thId": "ID",
|
|
"thName": "Name",
|
|
"thSubdomain": "Subdomain",
|
|
"thStatus": "Status",
|
|
"thDeployment": "Deployment",
|
|
"thDashboard": "Dashboard",
|
|
"thRelayPort": "Relay Port",
|
|
"thContainers": "Containers",
|
|
"noCustomers": "No customers.",
|
|
"imageUpdates": "NetBird Container Updates",
|
|
"checkUpdates": "Check for Updates",
|
|
"pullImages": "Pull Latest Images",
|
|
"updateAll": "Update All",
|
|
"clickCheckUpdates": "Click \"Check for Updates\" to compare local images with Docker Hub.",
|
|
"updateAvailable": "Update available",
|
|
"upToDate": "Up to date",
|
|
"needsUpdate": "Needs update",
|
|
"updateCustomer": "Update this customer",
|
|
"imageStatusTitle": "Image Status (vs. Docker Hub)",
|
|
"customerImageTitle": "Customer Container Status",
|
|
"thImage": "Image",
|
|
"thLocalDigest": "Local Digest",
|
|
"thHubDigest": "Hub Digest",
|
|
"confirmPull": "Pull the latest NetBird images from Docker Hub? This may take a few minutes.",
|
|
"pullStarted": "Image pull started in background. Re-checking in 5 seconds…",
|
|
"confirmUpdateAll": "Recreate containers for all customers that have outdated images? Running services will briefly restart.",
|
|
"updateAllStarted": "Update started in background.",
|
|
"updateDone": "Customer containers updated.",
|
|
"updating": "Updating…",
|
|
"updateAllProgress": "Updating customer containers one by one — please wait…",
|
|
"pulling": "Pulling…",
|
|
"pullStartedShort": "Pull started in background."
|
|
},
|
|
"userModal": {
|
|
"title": "New User",
|
|
"usernameLabel": "Username *",
|
|
"passwordLabel": "Password * (min 8 chars)",
|
|
"emailLabel": "Email",
|
|
"languageLabel": "Default Language",
|
|
"cancel": "Cancel",
|
|
"createUser": "Create User"
|
|
},
|
|
"mfa": {
|
|
"title": "Multi-Factor Authentication (MFA)",
|
|
"enableMfa": "Enable MFA for all local users",
|
|
"mfaDescription": "When enabled, local users must verify with a TOTP authenticator app after entering their password. Azure AD users are not affected.",
|
|
"saveMfaSettings": "Save MFA Settings",
|
|
"yourTotpStatus": "Your TOTP Status",
|
|
"totpActive": "Active",
|
|
"totpNotSetUp": "Not set up",
|
|
"disableMyTotp": "Disable my TOTP",
|
|
"enterCode": "Enter your 6-digit authenticator code",
|
|
"verify": "Verify",
|
|
"backToLogin": "Back to login",
|
|
"scanQrCode": "Scan this QR code with your authenticator app",
|
|
"orEnterManually": "Or enter this key manually:",
|
|
"verifyAndActivate": "Verify & Activate",
|
|
"resetMfa": "Reset MFA",
|
|
"confirmResetMfa": "Reset MFA for '{username}'? They will need to set up their authenticator again on next login.",
|
|
"mfaResetSuccess": "MFA reset for '{username}'.",
|
|
"mfaDisabled": "Your TOTP has been disabled.",
|
|
"mfaSaved": "MFA settings saved.",
|
|
"invalidCode": "Invalid code. Please try again.",
|
|
"codeExpired": "Verification expired. Please log in again."
|
|
},
|
|
"common": {
|
|
"loading": "Loading...",
|
|
"back": "Back",
|
|
"save": "Save",
|
|
"cancel": "Cancel",
|
|
"delete": "Delete",
|
|
"edit": "Edit",
|
|
"view": "View",
|
|
"start": "Start",
|
|
"stop": "Stop",
|
|
"restart": "Restart",
|
|
"disable": "Disable",
|
|
"enable": "Enable",
|
|
"resetPassword": "Reset Password",
|
|
"open": "Open",
|
|
"active": "Active",
|
|
"disabled": "Disabled"
|
|
},
|
|
"errors": {
|
|
"networkError": "Network error \u2014 server not reachable.",
|
|
"sessionExpired": "Session expired.",
|
|
"requestFailed": "Request failed.",
|
|
"serverError": "Server error (HTTP {status}).",
|
|
"unknownError": "An unknown error occurred.",
|
|
"uploadFailed": "Upload failed.",
|
|
"deleteFailed": "Delete failed: {error}",
|
|
"failedToLoadSettings": "Failed to load settings: {error}",
|
|
"failed": "Failed: {error}",
|
|
"logoUploadFailed": "Logo upload failed: {error}",
|
|
"failedToRemoveLogo": "Failed to remove logo: {error}",
|
|
"updateFailed": "Update failed: {error}",
|
|
"passwordResetFailed": "Password reset failed: {error}",
|
|
"selectFileFirst": "Please select a file first.",
|
|
"passwordsDoNotMatch": "Passwords do not match.",
|
|
"failedToLoadCredentials": "Failed to load credentials: {error}",
|
|
"azureNotConfigured": "Azure AD is not configured.",
|
|
"azureLoginFailed": "Azure AD login failed: {error}",
|
|
"actionFailed": "{action} failed: {error}"
|
|
},
|
|
"messages": {
|
|
"systemSettingsSaved": "System settings saved.",
|
|
"npmSettingsSaved": "NPM settings saved.",
|
|
"imageSettingsSaved": "Image settings saved.",
|
|
"brandingNameSaved": "Branding settings saved.",
|
|
"logoUploaded": "Logo uploaded successfully.",
|
|
"logoRemoved": "Logo removed.",
|
|
"azureSettingsSaved": "Azure AD settings saved.",
|
|
"dnsSettingsSaved": "DNS settings saved.",
|
|
"ldapSettingsSaved": "LDAP settings saved.",
|
|
"gitSettingsSaved": "Git settings saved.",
|
|
"updateStarted": "Update started. The app will restart shortly.",
|
|
"passwordChanged": "Password changed successfully.",
|
|
"setupUrlCopied": "Setup URL copied to clipboard.",
|
|
"copiedToClipboard": "Copied to clipboard.",
|
|
"userCreated": "User '{username}' created.",
|
|
"userDeleted": "User '{username}' deleted.",
|
|
"passwordResetFor": "Password reset for '{username}'.",
|
|
"newPasswordAlert": "New password for '{username}':\n\n{password}\n\nPlease save this password now. It will not be shown again.",
|
|
"confirmDeleteUser": "Delete user '{username}'? This cannot be undone.",
|
|
"confirmResetPassword": "Reset password for '{username}'? A new random password will be generated."
|
|
}
|
|
} |