Portainer
This guide explains how to configure single sign-on (SSO) between SmartLink and Portainer using OAuth2/OpenID Connect. Portainer Business Edition natively supports OAuth authentication.
Prerequisites
- Portainer Business Edition (BE) version 2.11 or higher
- Administrator access to Portainer
- Application configured in SmartLink with OpenID Connect
- Valid Portainer Business license
Note: OAuth authentication is only available in Portainer Business Edition. The Community Edition (CE) only supports local and LDAP authentication.
Configuration in SmartLink
1. Create the application
- Log in to SmartLink as an administrator
- Go to Applications → Add
- Create a new application:
- Name: Portainer
- URL:
https://portainer.example.com - Description: Docker/Kubernetes container management
- Icon: Choose the Portainer icon
2. Configure OpenID Connect
- In the Authentication tab
- Select OpenID Connect
- Note the information:
- Client ID:
portainer-xxxxxx - Client Secret:
secret-xxxxxx - Issuer URL:
https://your-smartlink.link.vaultys.org/api/oidc/[appid] - App ID:
[appid](unique application identifier in SmartLink)
- Client ID:
3. Allowed Redirect URLs
Add to Allowed Redirect URLs:
https://portainer.example.com/
https://portainer.example.com/#!/auth
4. Required Scopes
openidprofileemailgroups(for role mapping)
Configuration in Portainer
1. Access authentication settings
- Log in to Portainer as an administrator
- Go to Settings → Authentication
- Select OAuth as the authentication method
2. Configure OAuth2/OpenID Connect
Configure OAuth parameters:
Provider Information
- Client ID:
portainer-xxxxxx(from SmartLink) - Client Secret:
secret-xxxxxx(from SmartLink) - Authorization URL:
https://your-smartlink.link.vaultys.org/api/oidc/[appid]/authorize - Access token URL:
https://your-smartlink.link.vaultys.org/api/oidc/[appid]/token - Resource URL:
https://your-smartlink.link.vaultys.org/api/oidc/[appid]/userinfo - Redirect URL:
https://portainer.example.com/(automatically generated) - Logout URL:
https://your-smartlink.link.vaultys.org/logout - User identifier:
suboremail - Scopes:
openid profile email groups
Attribute Mapping
- Username:
email - Given name:
given_name - Family name:
family_name - Email:
email - Groups:
groups
3. Configuration with Docker
To deploy Portainer with OAuth configuration:
version: '3.8'
services:
portainer:
image: portainer/portainer-ee:latest
container_name: portainer
restart: unless-stopped
ports:
- "9443:9443"
- "8000:8000"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- portainer_data:/data
command: >
--http-disabled
--ssl-cert /certs/cert.pem
--ssl-key /certs/key.pem
environment:
- PORTAINER_OAUTH_CLIENT_ID=portainer-xxxxxx
- PORTAINER_OAUTH_CLIENT_SECRET=secret-xxxxxx
- PORTAINER_OAUTH_AUTH_URL=https://your-smartlink.link.vaultys.org/api/oidc/[appid]/authorize
- PORTAINER_OAUTH_TOKEN_URL=https://your-smartlink.link.vaultys.org/api/oidc/[appid]/token
- PORTAINER_OAUTH_RESOURCE_URL=https://your-smartlink.link.vaultys.org/api/oidc/[appid]/userinfo
- PORTAINER_OAUTH_REDIRECT_URL=https://portainer.example.com/
- PORTAINER_OAUTH_LOGOUT_URL=https://your-smartlink.link.vaultys.org/logout
- PORTAINER_OAUTH_USER_IDENTIFIER=sub
- PORTAINER_OAUTH_SCOPES=openid profile email groups
volumes:
portainer_data:
4. Configuration with Kubernetes
Helm deployment for Portainer:
# values.yaml
image:
repository: portainer/portainer-ee
tag: latest
service:
type: LoadBalancer
httpPort: 9000
httpsPort: 9443
persistence:
enabled: true
size: 10Gi
oauth:
enabled: true
clientId: "portainer-xxxxxx"
clientSecret: "secret-xxxxxx"
authorizationURL: "https://your-smartlink.link.vaultys.org/api/oidc/[appid]/authorize"
accessTokenURL: "https://your-smartlink.link.vaultys.org/api/oidc/[appid]/token"
resourceURL: "https://your-smartlink.link.vaultys.org/api/oidc/[appid]/userinfo"
redirectURL: "https://portainer.example.com/"
logoutURL: "https://your-smartlink.link.vaultys.org/logout"
userIdentifier: "sub"
scopes: "openid profile email groups"
Role and Permission Management
Automatic Role Configuration
Portainer supports multiple roles: Administrator, Operator, User, and HelpDesk.
Automatic User Creation
In Portainer, enable:
- Automatic user provisioning: ✅
- Default role for new users: User
Group Mapping to Roles
In Portainer's OAuth settings:
{
"group_mappings": [
{
"group": "portainer-admins",
"role": "Administrator"
},
{
"group": "portainer-operators",
"role": "Operator"
},
{
"group": "portainer-users",
"role": "User"
},
{
"group": "portainer-helpdesk",
"role": "HelpDesk"
}
]
}
Team Configuration
To organize users into teams:
- Settings → Teams
- Create teams corresponding to SmartLink groups
- Configure automatic mapping:
- Team membership provider: OAuth
- Group claim:
groups - Team assignment: Automatic
Endpoint Permissions
Configure access to different environments:
# Endpoint permissions configuration
endpoints:
- name: Production
groups:
- portainer-prod-admins: Administrator
- portainer-prod-users: User
- name: Staging
groups:
- portainer-dev-team: Administrator
- portainer-qa-team: User
- name: Development
groups:
- portainer-developers: Administrator
Configuration Testing
1. Initial Connection Test
- Log out of Portainer
- On the login page, click Login with OAuth
- You will be redirected to SmartLink
- Authenticate with your SmartLink credentials
- You should be logged in to Portainer
2. Permission Verification
# Using the Portainer API
curl -X GET https://portainer.example.com/api/users/me \
-H "Authorization: Bearer YOUR_TOKEN"
# Expected Response
{
"Id": 2,
"Username": "john.doe",
"Role": 1,
"UserTheme": "",
"PortainerAuthorizations": {
"EndpointResourcesAccess": {...},
"PortainerResourcesAccess": {...}
}
}
3. Docker CLI Test
# Docker context configuration
docker context create portainer \
--docker "host=tcp://portainer.example.com:2376,ca=ca.pem,cert=cert.pem,key=key.pem"
# Usage
docker context use portainer
docker ps
Environment Configuration
Adding Docker Environments
- Environments → Add environment
- Choose the type:
- Docker Standalone
- Docker Swarm
- Kubernetes
- Azure Container Instances
- Docker via API
Configuration for Docker Swarm
# docker-compose.yml for Portainer agent
version: '3.8'
services:
agent:
image: portainer/agent:latest
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /var/lib/docker/volumes:/var/lib/docker/volumes
networks:
- agent_network
deploy:
mode: global
placement:
constraints: [node.platform.os == linux]
networks:
agent_network:
driver: overlay
attachable: true
Configuration for Kubernetes
# portainer-agent-k8s.yaml
apiVersion: v1
kind: Namespace
metadata:
name: portainer
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: portainer-sa-clusteradmin
namespace: portainer
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: portainer-crb-clusteradmin
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: portainer-sa-clusteradmin
namespace: portainer
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: portainer-agent
namespace: portainer
spec:
selector:
matchLabels:
app: portainer-agent
template:
metadata:
labels:
app: portainer-agent
spec:
serviceAccountName: portainer-sa-clusteradmin
containers:
- name: portainer-agent
image: portainer/agent:latest
ports:
- containerPort: 9001
protocol: TCP
Troubleshooting
"Invalid OAuth configuration" Error
Issue: OAuth configuration is invalid
Solution:
- Check all URLs (watch out for trailing slashes)
- Test the endpoints:
curl https://your-smartlink.link.vaultys.org/api/oidc/[appid]/.well-known/openid-configuration - Check Portainer logs:
docker logs portainer
"User does not have access to any environment" Error
Issue: User is logged in but has no access
Solution:
- Check the user's groups in SmartLink
- Configure endpoint permissions
- Assign a default role to new users
Groups Not Synchronized
Issue: SmartLink groups are not mapped
Solution:
- Ensure the
groupsscope is requested - Test the UserInfo response:
curl -H "Authorization: Bearer TOKEN" \
https://your-smartlink.link.vaultys.org/api/oidc/[appid]/userinfo - Check the format of groups (should be an array)
SSL Certificate Error
Issue: SSL error during OAuth connection
Solution:
- Use valid certificates (not self-signed)
- For testing, temporarily disable verification:
environment:
- PORTAINER_OAUTH_SSO_INSECURE_SKIP_VERIFY=true - ⚠️ Never use in production
Security
Recommendations
- Mandatory HTTPS: Always use HTTPS
- Environment Isolation: Separate prod/staging/dev
- Strict RBAC: Use appropriate roles
- Audit Logs: Enable and monitor logs
- Secrets Rotation: Regularly change OAuth secrets
Enhanced Security Configuration
# Secure configuration
environment:
# Disable local authentication after OAuth configuration
- PORTAINER_AUTH_LOCAL_DISABLED=true
# Session timeout
- PORTAINER_SESSION_TIMEOUT=8h
# Enable audit logs
- PORTAINER_AUDIT_LOG=true
# Force HTTPS
- PORTAINER_HTTP_DISABLED=true
IP Access Limitation
# Nginx configuration to limit access
location / {
# Allow only certain IPs
allow 10.0.0.0/8;
allow 192.168.1.0/24;
deny all;
proxy_pass https://portainer:9443;
proxy_set_header Host $host;
}
Advanced Configuration
GitOps Integration
# ArgoCD configuration for Portainer
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: portainer
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/portainer/k8s
targetRevision: HEAD
path: charts/portainer
helm:
values: |
oauth:
enabled: true
clientId: portainer-xxxxxx
clientSecret: secret-xxxxxx
Monitoring with Prometheus
# Metrics configuration
environment:
- PORTAINER_METRICS_ENABLED=true
- PORTAINER_METRICS_PORT=9090
# Prometheus scrape config
scrape_configs:
- job_name: 'portainer'
static_configs:
- targets: ['portainer:9090']