📝 docs: Add documentation
This commit is contained in:
@@ -0,0 +1,387 @@
|
||||
# Contributors
|
||||
|
||||
Thank you to all the developers who have contributed to the PPanel project!
|
||||
|
||||
## Project Contributors
|
||||
|
||||
PPanel is an open-source project, and we welcome and appreciate all forms of contributions, including but not limited to:
|
||||
|
||||
- 💻 Code contributions
|
||||
- 📝 Documentation improvements
|
||||
- 🐛 Bug reports
|
||||
- 💡 Feature suggestions
|
||||
- 🌍 Translation work
|
||||
- ⭐ Stars and promotion
|
||||
|
||||
## Core Contributors
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
|
||||
const backendContributors = ref([])
|
||||
const frontendContributors = ref([])
|
||||
const backendLoading = ref(true)
|
||||
const frontendLoading = ref(true)
|
||||
|
||||
onMounted(async () => {
|
||||
// Fetch contributors from backend related repositories
|
||||
try {
|
||||
const repos = ['server', 'ppanel', 'ppanel-node']
|
||||
const contributorsMap = new Map()
|
||||
|
||||
for (const repo of repos) {
|
||||
const response = await fetch(`https://api.github.com/repos/perfect-panel/${repo}/contributors`)
|
||||
if (response.ok) {
|
||||
const contributors = await response.json()
|
||||
contributors.forEach(contributor => {
|
||||
if (!contributorsMap.has(contributor.login)) {
|
||||
contributorsMap.set(contributor.login, {
|
||||
login: contributor.login,
|
||||
avatar_url: contributor.avatar_url,
|
||||
html_url: contributor.html_url,
|
||||
contributions: contributor.contributions
|
||||
})
|
||||
} else {
|
||||
const existing = contributorsMap.get(contributor.login)
|
||||
existing.contributions += contributor.contributions
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
backendContributors.value = Array.from(contributorsMap.values())
|
||||
.sort((a, b) => b.contributions - a.contributions)
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch backend contributors:', error)
|
||||
} finally {
|
||||
backendLoading.value = false
|
||||
}
|
||||
|
||||
// Fetch contributors from frontend related repositories
|
||||
try {
|
||||
const repos = ['frontend', 'ppanel-web', 'ppanel-docs']
|
||||
const contributorsMap = new Map()
|
||||
|
||||
for (const repo of repos) {
|
||||
const response = await fetch(`https://api.github.com/repos/perfect-panel/${repo}/contributors`)
|
||||
if (response.ok) {
|
||||
const contributors = await response.json()
|
||||
contributors.forEach(contributor => {
|
||||
if (!contributorsMap.has(contributor.login)) {
|
||||
contributorsMap.set(contributor.login, {
|
||||
login: contributor.login,
|
||||
avatar_url: contributor.avatar_url,
|
||||
html_url: contributor.html_url,
|
||||
contributions: contributor.contributions
|
||||
})
|
||||
} else {
|
||||
const existing = contributorsMap.get(contributor.login)
|
||||
existing.contributions += contributor.contributions
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
frontendContributors.value = Array.from(contributorsMap.values())
|
||||
.sort((a, b) => b.contributions - a.contributions)
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch frontend contributors:', error)
|
||||
} finally {
|
||||
frontendLoading.value = false
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
### Backend Repository Contributors
|
||||
|
||||
<div v-if="backendLoading" class="contributors-loading">
|
||||
<div class="loading-spinner"></div>
|
||||
<p>Loading contributors...</p>
|
||||
</div>
|
||||
|
||||
<div v-else-if="backendContributors.length === 0" class="contributors-empty">
|
||||
<p>No contributors data available</p>
|
||||
</div>
|
||||
|
||||
<div v-else>
|
||||
<div class="contributors-grid">
|
||||
<a
|
||||
v-for="contributor in backendContributors"
|
||||
:key="contributor.login"
|
||||
:href="contributor.html_url"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="contributor-card"
|
||||
>
|
||||
<img
|
||||
:src="contributor.avatar_url"
|
||||
:alt="contributor.login"
|
||||
class="contributor-avatar"
|
||||
loading="lazy"
|
||||
/>
|
||||
<div class="contributor-info">
|
||||
<div class="contributor-name" :title="contributor.login">{{ contributor.login }}</div>
|
||||
<div class="contributor-contributions">
|
||||
<svg class="contribution-icon" viewBox="0 0 16 16" width="12" height="12" fill="currentColor">
|
||||
<path d="M8 .25a.75.75 0 0 1 .673.418l1.882 3.815 4.21.612a.75.75 0 0 1 .416 1.279l-3.046 2.97.719 4.192a.751.751 0 0 1-1.088.791L8 12.347l-3.766 1.98a.75.75 0 0 1-1.088-.79l.72-4.194L.818 6.374a.75.75 0 0 1 .416-1.28l4.21-.611L7.327.668A.75.75 0 0 1 8 .25Z"></path>
|
||||
</svg>
|
||||
{{ contributor.contributions }} contributions
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
### Frontend Repository Contributors
|
||||
|
||||
<div v-if="frontendLoading" class="contributors-loading">
|
||||
<div class="loading-spinner"></div>
|
||||
<p>Loading contributors...</p>
|
||||
</div>
|
||||
|
||||
<div v-else-if="frontendContributors.length === 0" class="contributors-empty">
|
||||
<p>No contributors data available</p>
|
||||
</div>
|
||||
|
||||
<div v-else>
|
||||
<div class="contributors-grid">
|
||||
<a
|
||||
v-for="contributor in frontendContributors"
|
||||
:key="contributor.login"
|
||||
:href="contributor.html_url"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="contributor-card"
|
||||
>
|
||||
<img
|
||||
:src="contributor.avatar_url"
|
||||
:alt="contributor.login"
|
||||
class="contributor-avatar"
|
||||
loading="lazy"
|
||||
/>
|
||||
<div class="contributor-info">
|
||||
<div class="contributor-name" :title="contributor.login">{{ contributor.login }}</div>
|
||||
<div class="contributor-contributions">
|
||||
<svg class="contribution-icon" viewBox="0 0 16 16" width="12" height="12" fill="currentColor">
|
||||
<path d="M8 .25a.75.75 0 0 1 .673.418l1.882 3.815 4.21.612a.75.75 0 0 1 .416 1.279l-3.046 2.97.719 4.192a.751.751 0 0 1-1.088.791L8 12.347l-3.766 1.98a.75.75 0 0 1-1.088-.79l.72-4.194L.818 6.374a.75.75 0 0 1 .416-1.28l4.21-.611L7.327.668A.75.75 0 0 1 8 .25Z"></path>
|
||||
</svg>
|
||||
{{ contributor.contributions }} contributions
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style scoped>
|
||||
.contributors-loading {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 3rem;
|
||||
color: var(--vp-c-text-2);
|
||||
}
|
||||
|
||||
.loading-spinner {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border: 3px solid var(--vp-c-divider);
|
||||
border-top-color: var(--vp-c-brand);
|
||||
border-radius: 50%;
|
||||
animation: spin 0.8s linear infinite;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
.contributors-empty {
|
||||
text-align: center;
|
||||
padding: 2rem;
|
||||
color: var(--vp-c-text-3);
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.contributors-stats {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
margin-bottom: 1.5rem;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.stat-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
padding: 0.5rem 1rem;
|
||||
background: var(--vp-c-bg-soft);
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
border-radius: 20px;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
color: var(--vp-c-text-2);
|
||||
}
|
||||
|
||||
.contributors-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
|
||||
gap: 1rem;
|
||||
margin: 1.5rem 0;
|
||||
}
|
||||
|
||||
.contributor-card {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 1rem;
|
||||
background: var(--vp-c-bg-soft);
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
border-radius: 12px;
|
||||
text-decoration: none;
|
||||
color: var(--vp-c-text-1);
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.contributor-card::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 2px;
|
||||
background: linear-gradient(90deg, var(--vp-c-brand), var(--vp-c-brand-light));
|
||||
transform: scaleX(0);
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.contributor-card:hover {
|
||||
border-color: var(--vp-c-brand-light);
|
||||
transform: translateY(-4px);
|
||||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
|
||||
}
|
||||
|
||||
.contributor-card:hover::before {
|
||||
transform: scaleX(1);
|
||||
}
|
||||
|
||||
.contributor-avatar {
|
||||
width: 56px;
|
||||
height: 56px;
|
||||
border-radius: 50%;
|
||||
margin-right: 1rem;
|
||||
border: 2px solid var(--vp-c-divider);
|
||||
transition: all 0.3s ease;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.contributor-card:hover .contributor-avatar {
|
||||
border-color: var(--vp-c-brand);
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
.contributor-info {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.contributor-name {
|
||||
font-weight: 600;
|
||||
font-size: 15px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
margin-bottom: 0.25rem;
|
||||
color: var(--vp-c-text-1);
|
||||
}
|
||||
|
||||
.contributor-contributions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.25rem;
|
||||
font-size: 13px;
|
||||
color: var(--vp-c-text-2);
|
||||
}
|
||||
|
||||
.contribution-icon {
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.contributors-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.contributors-stats {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.stat-badge {
|
||||
width: 100%;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.contributor-card:hover {
|
||||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
### Reporting Issues
|
||||
|
||||
If you find a bug or have a feature suggestion:
|
||||
|
||||
1. Search [GitHub Issues](https://github.com/perfect-panel/frontend/issues) to see if a similar issue exists
|
||||
2. If not, create a new Issue
|
||||
3. Provide detailed information:
|
||||
- Problem description
|
||||
- Steps to reproduce
|
||||
- Expected behavior
|
||||
- Actual behavior
|
||||
- Environment info (browser, OS, etc.)
|
||||
- Screenshots or error logs (if applicable)
|
||||
|
||||
### Documentation Contributions
|
||||
|
||||
Documentation is equally important! You can:
|
||||
|
||||
- Fix typos and grammar errors
|
||||
- Improve clarity of existing documentation
|
||||
- Add missing documentation
|
||||
- Translate documentation to other languages
|
||||
- Add usage examples and tutorials
|
||||
|
||||
Documentation source files are located in the `/docs` directory.
|
||||
|
||||
### Translation Contributions
|
||||
|
||||
We welcome translating PPanel into more languages:
|
||||
|
||||
1. Check if there's already a folder for the target language in `/docs`
|
||||
2. If not, create a new language folder (e.g., `/docs/ja` for Japanese)
|
||||
3. Copy the English or Chinese version as a base
|
||||
4. Translate the content
|
||||
5. Add new language configuration in `.vitepress/config.mts`
|
||||
6. Submit a Pull Request
|
||||
|
||||
## Community
|
||||
|
||||
Join our community and connect with other developers:
|
||||
|
||||
- **GitHub Discussions**: [Discussion Forum](https://github.com/perfect-panel/frontend/discussions)
|
||||
- **GitHub Issues**: [Issue Tracker](https://github.com/perfect-panel/frontend/issues)
|
||||
- **Telegram**: [Join Group](https://t.me/PPanelChat)
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
We are committed to providing a friendly, safe, and welcoming environment for everyone. Please read and follow our [Code of Conduct](https://github.com/perfect-panel/frontend/blob/main/CODE_OF_CONDUCT.md).
|
||||
|
||||
## Acknowledgments
|
||||
|
||||
Special thanks to all developers, testers, documentation writers, and community members who have contributed to the PPanel project. You make PPanel better!
|
||||
|
||||
## License
|
||||
|
||||
By contributing code, you agree that your contributions will be licensed under the project's [GNU License](https://github.com/perfect-panel/frontend/blob/main/LICENSE).
|
||||
@@ -0,0 +1,507 @@
|
||||
# Installation
|
||||
|
||||
This guide will help you deploy PPanel on your server using Docker.
|
||||
|
||||
## System Requirements
|
||||
|
||||
### Minimum Requirements
|
||||
- **Operating System**: Linux (Ubuntu 20.04+, Debian 10+, CentOS 8+)
|
||||
- **CPU**: 1 core
|
||||
- **Memory**: 512MB RAM
|
||||
- **Storage**: 1GB available disk space
|
||||
- **Docker**: 20.10+
|
||||
- **Docker Compose**: 2.0+ (optional but recommended)
|
||||
|
||||
### Recommended Requirements
|
||||
- **CPU**: 2+ cores
|
||||
- **Memory**: 2GB+ RAM
|
||||
- **Storage**: 5GB+ available disk space
|
||||
|
||||
## Prerequisites
|
||||
|
||||
### Install Docker
|
||||
|
||||
If you haven't installed Docker yet, please follow the official installation guide:
|
||||
|
||||
**Ubuntu/Debian:**
|
||||
```bash
|
||||
# Update package index
|
||||
sudo apt-get update
|
||||
|
||||
# Install required packages
|
||||
sudo apt-get install -y ca-certificates curl gnupg lsb-release
|
||||
|
||||
# Add Docker's official GPG key
|
||||
sudo mkdir -p /etc/apt/keyrings
|
||||
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
|
||||
|
||||
# Set up the repository
|
||||
echo \
|
||||
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
|
||||
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
|
||||
|
||||
# Install Docker Engine
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
|
||||
```
|
||||
|
||||
**CentOS/RHEL:**
|
||||
```bash
|
||||
# Install yum-utils
|
||||
sudo yum install -y yum-utils
|
||||
|
||||
# Add Docker repository
|
||||
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
|
||||
|
||||
# Install Docker Engine
|
||||
sudo yum install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
|
||||
|
||||
# Start Docker service
|
||||
sudo systemctl start docker
|
||||
sudo systemctl enable docker
|
||||
```
|
||||
|
||||
### Verify Installation
|
||||
|
||||
```bash
|
||||
# Check Docker version
|
||||
docker --version
|
||||
|
||||
# Check Docker Compose version
|
||||
docker compose version
|
||||
|
||||
# Test Docker installation
|
||||
sudo docker run hello-world
|
||||
```
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Method 1: Using Docker Run
|
||||
|
||||
#### Step 1: Pull the Image
|
||||
|
||||
```bash
|
||||
# Pull latest version
|
||||
docker pull ppanel/ppanel:latest
|
||||
|
||||
# Or pull a specific version
|
||||
docker pull ppanel/ppanel:v0.1.2
|
||||
```
|
||||
|
||||
#### Step 2: Prepare Configuration
|
||||
|
||||
Create a configuration directory and prepare the configuration file:
|
||||
|
||||
```bash
|
||||
# Create configuration directory
|
||||
mkdir -p ppanel-config
|
||||
|
||||
# Create configuration file
|
||||
cat > ppanel-config/ppanel.yaml <<EOF
|
||||
# PPanel Configuration
|
||||
server:
|
||||
host: 0.0.0.0
|
||||
port: 8080
|
||||
|
||||
database:
|
||||
type: sqlite
|
||||
path: /app/data/ppanel.db
|
||||
|
||||
# Add more configuration as needed
|
||||
EOF
|
||||
```
|
||||
|
||||
::: tip
|
||||
For detailed configuration options, please refer to the [Configuration Guide](/guide/configuration).
|
||||
:::
|
||||
|
||||
#### Step 3: Run Container
|
||||
|
||||
```bash
|
||||
docker run -d \
|
||||
--name ppanel \
|
||||
-p 8080:8080 \
|
||||
-v $(pwd)/ppanel-config:/app/etc:ro \
|
||||
-v ppanel-data:/app/data \
|
||||
--restart unless-stopped \
|
||||
ppanel/ppanel:latest
|
||||
```
|
||||
|
||||
**Parameter Explanation:**
|
||||
- `-d`: Run container in detached mode (background)
|
||||
- `--name ppanel`: Set container name
|
||||
- `-p 8080:8080`: Map container port 8080 to host port 8080
|
||||
- `-v $(pwd)/ppanel-config:/app/etc:ro`: Mount configuration directory (read-only)
|
||||
- `-v ppanel-data:/app/data`: Create a volume for persistent data storage
|
||||
- `--restart unless-stopped`: Auto-restart container unless manually stopped
|
||||
|
||||
#### Step 4: Verify Running Status
|
||||
|
||||
```bash
|
||||
# Check container status
|
||||
docker ps | grep ppanel
|
||||
|
||||
# View logs
|
||||
docker logs -f ppanel
|
||||
|
||||
# Check if service is accessible
|
||||
curl http://localhost:8080
|
||||
```
|
||||
|
||||
### Method 2: Using Docker Compose (Recommended)
|
||||
|
||||
#### Step 1: Create docker-compose.yml
|
||||
|
||||
```yaml
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
ppanel:
|
||||
image: ppanel/ppanel:latest
|
||||
container_name: ppanel
|
||||
ports:
|
||||
- "8080:8080"
|
||||
volumes:
|
||||
- ./ppanel-config:/app/etc:ro
|
||||
- ppanel-data:/app/data
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- TZ=UTC
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:8080/health"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 40s
|
||||
|
||||
volumes:
|
||||
ppanel-data:
|
||||
driver: local
|
||||
```
|
||||
|
||||
#### Step 2: Prepare Configuration
|
||||
|
||||
```bash
|
||||
# Create configuration directory
|
||||
mkdir -p ppanel-config
|
||||
|
||||
# Copy or create your configuration file
|
||||
# See Configuration Guide for details
|
||||
```
|
||||
|
||||
#### Step 3: Start Services
|
||||
|
||||
```bash
|
||||
# Start in detached mode
|
||||
docker compose up -d
|
||||
|
||||
# View logs
|
||||
docker compose logs -f
|
||||
|
||||
# Check status
|
||||
docker compose ps
|
||||
```
|
||||
|
||||
## Post-Installation
|
||||
|
||||
### Access the Application
|
||||
|
||||
After successful installation, you can access:
|
||||
|
||||
- **User Panel**: `http://your-server-ip:8080`
|
||||
- **Admin Panel**: `http://your-server-ip:8080/admin`
|
||||
|
||||
::: warning Default Credentials
|
||||
Please change the default admin password immediately after first login for security.
|
||||
:::
|
||||
|
||||
### Configure Reverse Proxy (Optional)
|
||||
|
||||
For production deployment, it's recommended to use Nginx or Caddy as a reverse proxy to enable HTTPS.
|
||||
|
||||
**Nginx Example:**
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 80;
|
||||
server_name your-domain.com;
|
||||
|
||||
location / {
|
||||
proxy_pass http://localhost:8080;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Caddy Example:**
|
||||
|
||||
```
|
||||
your-domain.com {
|
||||
reverse_proxy localhost:8080
|
||||
}
|
||||
```
|
||||
|
||||
## Container Management
|
||||
|
||||
### View Logs
|
||||
|
||||
```bash
|
||||
# Docker Run
|
||||
docker logs -f ppanel
|
||||
|
||||
# Docker Compose
|
||||
docker compose logs -f
|
||||
```
|
||||
|
||||
### Stop Container
|
||||
|
||||
```bash
|
||||
# Docker Run
|
||||
docker stop ppanel
|
||||
|
||||
# Docker Compose
|
||||
docker compose stop
|
||||
```
|
||||
|
||||
### Restart Container
|
||||
|
||||
```bash
|
||||
# Docker Run
|
||||
docker restart ppanel
|
||||
|
||||
# Docker Compose
|
||||
docker compose restart
|
||||
```
|
||||
|
||||
### Remove Container
|
||||
|
||||
```bash
|
||||
# Docker Run
|
||||
docker stop ppanel
|
||||
docker rm ppanel
|
||||
|
||||
# Docker Compose
|
||||
docker compose down
|
||||
```
|
||||
|
||||
::: warning Data Persistence
|
||||
Removing containers will not delete volumes. To remove volumes as well, use:
|
||||
```bash
|
||||
docker compose down -v
|
||||
```
|
||||
:::
|
||||
|
||||
## Upgrading
|
||||
|
||||
### Backup Configuration
|
||||
|
||||
Before upgrading, backup your configuration and data:
|
||||
|
||||
```bash
|
||||
# Backup configuration
|
||||
tar czf ppanel-config-backup-$(date +%Y%m%d).tar.gz ppanel-config/
|
||||
|
||||
# Backup data volume
|
||||
docker run --rm \
|
||||
-v ppanel-data:/data \
|
||||
-v $(pwd):/backup \
|
||||
alpine tar czf /backup/ppanel-data-backup-$(date +%Y%m%d).tar.gz /data
|
||||
```
|
||||
|
||||
### Upgrade Steps
|
||||
|
||||
#### Using Docker Run
|
||||
|
||||
```bash
|
||||
# Pull latest image
|
||||
docker pull ppanel/ppanel:latest
|
||||
|
||||
# Stop and remove old container
|
||||
docker stop ppanel
|
||||
docker rm ppanel
|
||||
|
||||
# Start new container with same configuration
|
||||
docker run -d \
|
||||
--name ppanel \
|
||||
-p 8080:8080 \
|
||||
-v $(pwd)/ppanel-config:/app/etc:ro \
|
||||
-v ppanel-data:/app/data \
|
||||
--restart unless-stopped \
|
||||
ppanel/ppanel:latest
|
||||
```
|
||||
|
||||
#### Using Docker Compose
|
||||
|
||||
```bash
|
||||
# Pull latest image
|
||||
docker compose pull
|
||||
|
||||
# Recreate containers with new image
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
### Verify Upgrade
|
||||
|
||||
```bash
|
||||
# Check container is running
|
||||
docker ps | grep ppanel
|
||||
|
||||
# Check logs for any errors
|
||||
docker logs ppanel
|
||||
|
||||
# Verify application is accessible
|
||||
curl http://localhost:8080
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Container Exits Immediately
|
||||
|
||||
**Check architecture compatibility:**
|
||||
```bash
|
||||
# Check host architecture
|
||||
uname -m
|
||||
|
||||
# Check image architecture
|
||||
docker image inspect ppanel/ppanel:latest --format '{{.Architecture}}'
|
||||
```
|
||||
|
||||
**Check logs:**
|
||||
```bash
|
||||
docker logs ppanel
|
||||
```
|
||||
|
||||
### Cannot Access Service
|
||||
|
||||
1. **Check if container is running:**
|
||||
```bash
|
||||
docker ps | grep ppanel
|
||||
```
|
||||
|
||||
2. **Check port mapping:**
|
||||
```bash
|
||||
docker port ppanel
|
||||
```
|
||||
|
||||
3. **Check firewall rules:**
|
||||
```bash
|
||||
# Ubuntu/Debian
|
||||
sudo ufw status
|
||||
sudo ufw allow 8080
|
||||
|
||||
# CentOS/RHEL
|
||||
sudo firewall-cmd --list-ports
|
||||
sudo firewall-cmd --add-port=8080/tcp --permanent
|
||||
sudo firewall-cmd --reload
|
||||
```
|
||||
|
||||
### Configuration Not Taking Effect
|
||||
|
||||
1. **Verify mount path:**
|
||||
```bash
|
||||
docker exec ppanel ls -la /app/etc
|
||||
```
|
||||
|
||||
2. **Check configuration syntax:**
|
||||
```bash
|
||||
docker exec ppanel cat /app/etc/ppanel.yaml
|
||||
```
|
||||
|
||||
3. **Restart container:**
|
||||
```bash
|
||||
docker restart ppanel
|
||||
```
|
||||
|
||||
### Performance Issues
|
||||
|
||||
1. **Check resource usage:**
|
||||
```bash
|
||||
docker stats ppanel
|
||||
```
|
||||
|
||||
2. **Increase container resources** (if using Docker Desktop):
|
||||
- Open Docker Desktop Settings
|
||||
- Go to Resources
|
||||
- Increase CPU and Memory allocation
|
||||
|
||||
3. **Check disk space:**
|
||||
```bash
|
||||
df -h
|
||||
docker system df
|
||||
```
|
||||
|
||||
## Advanced Configuration
|
||||
|
||||
### Using Environment Variables
|
||||
|
||||
You can override configuration via environment variables:
|
||||
|
||||
```bash
|
||||
docker run -d \
|
||||
--name ppanel \
|
||||
-p 8080:8080 \
|
||||
-e SERVER_PORT=8080 \
|
||||
-e DATABASE_TYPE=sqlite \
|
||||
-v $(pwd)/ppanel-config:/app/etc:ro \
|
||||
-v ppanel-data:/app/data \
|
||||
--restart unless-stopped \
|
||||
ppanel/ppanel:latest
|
||||
```
|
||||
|
||||
### Running Multiple Instances
|
||||
|
||||
To run multiple instances, use different ports and container names:
|
||||
|
||||
```bash
|
||||
# Instance 1
|
||||
docker run -d \
|
||||
--name ppanel-1 \
|
||||
-p 8081:8080 \
|
||||
-v $(pwd)/ppanel-config-1:/app/etc:ro \
|
||||
-v ppanel-data-1:/app/data \
|
||||
ppanel/ppanel:latest
|
||||
|
||||
# Instance 2
|
||||
docker run -d \
|
||||
--name ppanel-2 \
|
||||
-p 8082:8080 \
|
||||
-v $(pwd)/ppanel-config-2:/app/etc:ro \
|
||||
-v ppanel-data-2:/app/data \
|
||||
ppanel/ppanel:latest
|
||||
```
|
||||
|
||||
### Custom Network
|
||||
|
||||
Create a custom Docker network for better isolation:
|
||||
|
||||
```bash
|
||||
# Create network
|
||||
docker network create ppanel-net
|
||||
|
||||
# Run container on custom network
|
||||
docker run -d \
|
||||
--name ppanel \
|
||||
--network ppanel-net \
|
||||
-p 8080:8080 \
|
||||
-v $(pwd)/ppanel-config:/app/etc:ro \
|
||||
-v ppanel-data:/app/data \
|
||||
ppanel/ppanel:latest
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
- [Configuration Guide](/guide/configuration) - Learn about detailed configuration options
|
||||
- [Admin Dashboard](/admin/dashboard) - Start managing your panel
|
||||
- [API Reference](/api/reference) - Integrate with PPanel API
|
||||
|
||||
## Need Help?
|
||||
|
||||
If you encounter any issues:
|
||||
|
||||
1. Check the [Troubleshooting](#troubleshooting) section above
|
||||
2. Search [GitHub Issues](https://github.com/perfect-panel/ppanel/issues)
|
||||
3. Join our community discussions
|
||||
4. Create a new issue with detailed logs and system information
|
||||
@@ -0,0 +1,585 @@
|
||||
# Binary Deployment
|
||||
|
||||
This guide shows you how to deploy PPanel using pre-built binary executables. This method is suitable for users who prefer not to use Docker or need more control over the deployment.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- **Operating System**: Linux (Ubuntu 20.04+, Debian 10+, CentOS 8+)
|
||||
- **Architecture**: amd64 (x86_64) or arm64
|
||||
- **Permissions**: Root or sudo access
|
||||
- **Dependencies**: None (binaries are statically compiled)
|
||||
|
||||
## Download Binary
|
||||
|
||||
### Step 1: Check System Architecture
|
||||
|
||||
```bash
|
||||
# Check your system architecture
|
||||
uname -m
|
||||
# Output: x86_64 (amd64) or aarch64 (arm64)
|
||||
```
|
||||
|
||||
### Step 2: Download Latest Release
|
||||
|
||||
Visit the [GitHub Releases](https://github.com/perfect-panel/ppanel/releases) page or download directly:
|
||||
|
||||
```bash
|
||||
# Create installation directory
|
||||
sudo mkdir -p /opt/ppanel
|
||||
cd /opt/ppanel
|
||||
|
||||
# Download for Linux amd64
|
||||
wget https://github.com/perfect-panel/ppanel/releases/latest/download/ppanel-linux-amd64.tar.gz
|
||||
|
||||
# Or for Linux arm64
|
||||
# wget https://github.com/perfect-panel/ppanel/releases/latest/download/ppanel-linux-arm64.tar.gz
|
||||
|
||||
# Extract
|
||||
tar -xzf ppanel-linux-amd64.tar.gz
|
||||
|
||||
# Verify extracted files
|
||||
ls -la
|
||||
```
|
||||
|
||||
Expected files:
|
||||
```
|
||||
/opt/ppanel/
|
||||
├── ppanel-server # Main server binary
|
||||
├── gateway # Gateway binary
|
||||
└── etc/ # Configuration directory
|
||||
└── ppanel.yaml # Configuration file
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
### Step 1: Prepare Configuration
|
||||
|
||||
```bash
|
||||
# Copy sample configuration
|
||||
sudo cp etc/ppanel.yaml etc/ppanel.yaml.backup
|
||||
|
||||
# Edit configuration
|
||||
sudo nano etc/ppanel.yaml
|
||||
```
|
||||
|
||||
**Basic Configuration Example:**
|
||||
|
||||
```yaml
|
||||
server:
|
||||
host: 0.0.0.0
|
||||
port: 8080
|
||||
mode: release # debug, release, or test
|
||||
|
||||
database:
|
||||
type: sqlite
|
||||
path: /opt/ppanel/data/ppanel.db
|
||||
# For MySQL/PostgreSQL:
|
||||
# type: mysql
|
||||
# host: localhost
|
||||
# port: 3306
|
||||
# user: ppanel
|
||||
# password: your_password
|
||||
# database: ppanel
|
||||
|
||||
log:
|
||||
level: info # debug, info, warn, error
|
||||
path: /opt/ppanel/logs
|
||||
|
||||
gateway:
|
||||
port: 8080
|
||||
timeout: 30s
|
||||
```
|
||||
|
||||
### Step 2: Create Required Directories
|
||||
|
||||
```bash
|
||||
# Create data and log directories
|
||||
sudo mkdir -p /opt/ppanel/data
|
||||
sudo mkdir -p /opt/ppanel/logs
|
||||
|
||||
# Set proper permissions
|
||||
sudo chmod 755 /opt/ppanel
|
||||
sudo chmod 700 /opt/ppanel/data
|
||||
sudo chmod 755 /opt/ppanel/logs
|
||||
```
|
||||
|
||||
## Running the Service
|
||||
|
||||
### Method 1: Direct Execution (Testing)
|
||||
|
||||
For quick testing:
|
||||
|
||||
```bash
|
||||
# Make binaries executable
|
||||
sudo chmod +x /opt/ppanel/ppanel-server
|
||||
sudo chmod +x /opt/ppanel/gateway
|
||||
|
||||
# Run server directly
|
||||
cd /opt/ppanel
|
||||
sudo ./ppanel-server
|
||||
|
||||
# In another terminal, run gateway (if separate)
|
||||
# sudo ./gateway
|
||||
```
|
||||
|
||||
Press `Ctrl+C` to stop.
|
||||
|
||||
### Method 2: Systemd Service (Recommended)
|
||||
|
||||
Create a systemd service for production deployment:
|
||||
|
||||
#### Step 1: Create Service File
|
||||
|
||||
```bash
|
||||
sudo nano /etc/systemd/system/ppanel.service
|
||||
```
|
||||
|
||||
**Service File Content:**
|
||||
|
||||
```ini
|
||||
[Unit]
|
||||
Description=PPanel Server
|
||||
Documentation=https://github.com/perfect-panel/ppanel
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=root
|
||||
WorkingDirectory=/opt/ppanel
|
||||
ExecStart=/opt/ppanel/ppanel-server
|
||||
Restart=always
|
||||
RestartSec=10
|
||||
|
||||
# Security settings
|
||||
NoNewPrivileges=true
|
||||
PrivateTmp=true
|
||||
ProtectSystem=strict
|
||||
ProtectHome=true
|
||||
ReadWritePaths=/opt/ppanel/data /opt/ppanel/logs
|
||||
|
||||
# Resource limits
|
||||
LimitNOFILE=65535
|
||||
LimitNPROC=4096
|
||||
|
||||
# Logging
|
||||
StandardOutput=journal
|
||||
StandardError=journal
|
||||
SyslogIdentifier=ppanel
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
#### Step 2: Enable and Start Service
|
||||
|
||||
```bash
|
||||
# Reload systemd
|
||||
sudo systemctl daemon-reload
|
||||
|
||||
# Enable service (start on boot)
|
||||
sudo systemctl enable ppanel
|
||||
|
||||
# Start service
|
||||
sudo systemctl start ppanel
|
||||
|
||||
# Check status
|
||||
sudo systemctl status ppanel
|
||||
```
|
||||
|
||||
## Service Management
|
||||
|
||||
### Check Status
|
||||
|
||||
```bash
|
||||
# Check if service is running
|
||||
sudo systemctl status ppanel
|
||||
|
||||
# View detailed status
|
||||
sudo systemctl show ppanel
|
||||
```
|
||||
|
||||
### View Logs
|
||||
|
||||
```bash
|
||||
# View systemd logs
|
||||
sudo journalctl -u ppanel -f
|
||||
|
||||
# View last 100 lines
|
||||
sudo journalctl -u ppanel -n 100
|
||||
|
||||
# View application logs
|
||||
sudo tail -f /opt/ppanel/logs/ppanel.log
|
||||
```
|
||||
|
||||
### Start/Stop/Restart
|
||||
|
||||
```bash
|
||||
# Start service
|
||||
sudo systemctl start ppanel
|
||||
|
||||
# Stop service
|
||||
sudo systemctl stop ppanel
|
||||
|
||||
# Restart service
|
||||
sudo systemctl restart ppanel
|
||||
|
||||
# Reload configuration (if supported)
|
||||
sudo systemctl reload ppanel
|
||||
```
|
||||
|
||||
### Enable/Disable Auto-start
|
||||
|
||||
```bash
|
||||
# Enable auto-start on boot
|
||||
sudo systemctl enable ppanel
|
||||
|
||||
# Disable auto-start
|
||||
sudo systemctl disable ppanel
|
||||
|
||||
# Check if enabled
|
||||
sudo systemctl is-enabled ppanel
|
||||
```
|
||||
|
||||
## Post-Installation
|
||||
|
||||
### Verify Installation
|
||||
|
||||
```bash
|
||||
# Check if service is listening
|
||||
sudo netstat -tlnp | grep 8080
|
||||
|
||||
# Or use ss
|
||||
sudo ss -tlnp | grep 8080
|
||||
|
||||
# Test HTTP access
|
||||
curl http://localhost:8080
|
||||
|
||||
# Check process
|
||||
ps aux | grep ppanel
|
||||
```
|
||||
|
||||
### Access the Application
|
||||
|
||||
- **User Panel**: `http://your-server-ip:8080`
|
||||
- **Admin Panel**: `http://your-server-ip:8080/admin`
|
||||
|
||||
### Configure Firewall
|
||||
|
||||
```bash
|
||||
# Ubuntu/Debian (UFW)
|
||||
sudo ufw allow 8080/tcp
|
||||
sudo ufw status
|
||||
|
||||
# CentOS/RHEL (firewalld)
|
||||
sudo firewall-cmd --permanent --add-port=8080/tcp
|
||||
sudo firewall-cmd --reload
|
||||
sudo firewall-cmd --list-ports
|
||||
```
|
||||
|
||||
### Setup Reverse Proxy
|
||||
|
||||
For production, use Nginx or Caddy as reverse proxy:
|
||||
|
||||
**Nginx Configuration** (`/etc/nginx/sites-available/ppanel`):
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 80;
|
||||
server_name your-domain.com;
|
||||
|
||||
location / {
|
||||
proxy_pass http://localhost:8080;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
|
||||
# WebSocket support
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Enable the configuration:
|
||||
```bash
|
||||
sudo ln -s /etc/nginx/sites-available/ppanel /etc/nginx/sites-enabled/
|
||||
sudo nginx -t
|
||||
sudo systemctl reload nginx
|
||||
```
|
||||
|
||||
## Upgrading
|
||||
|
||||
### Backup Before Upgrade
|
||||
|
||||
```bash
|
||||
# Stop service
|
||||
sudo systemctl stop ppanel
|
||||
|
||||
# Backup current version
|
||||
sudo cp -r /opt/ppanel /opt/ppanel-backup-$(date +%Y%m%d)
|
||||
|
||||
# Backup database
|
||||
sudo cp /opt/ppanel/data/ppanel.db /opt/ppanel/data/ppanel.db.backup-$(date +%Y%m%d)
|
||||
|
||||
# Backup configuration
|
||||
sudo cp /opt/ppanel/etc/ppanel.yaml /opt/ppanel/etc/ppanel.yaml.backup-$(date +%Y%m%d)
|
||||
```
|
||||
|
||||
### Download and Install New Version
|
||||
|
||||
```bash
|
||||
# Download new version
|
||||
cd /tmp
|
||||
wget https://github.com/perfect-panel/ppanel/releases/latest/download/ppanel-linux-amd64.tar.gz
|
||||
|
||||
# Extract to temporary location
|
||||
mkdir ppanel-new
|
||||
tar -xzf ppanel-linux-amd64.tar.gz -C ppanel-new
|
||||
|
||||
# Backup old binaries
|
||||
sudo mv /opt/ppanel/ppanel-server /opt/ppanel/ppanel-server.old
|
||||
sudo mv /opt/ppanel/gateway /opt/ppanel/gateway.old
|
||||
|
||||
# Install new binaries
|
||||
sudo cp ppanel-new/ppanel-server /opt/ppanel/
|
||||
sudo cp ppanel-new/gateway /opt/ppanel/
|
||||
|
||||
# Set permissions
|
||||
sudo chmod +x /opt/ppanel/ppanel-server
|
||||
sudo chmod +x /opt/ppanel/gateway
|
||||
|
||||
# Start service
|
||||
sudo systemctl start ppanel
|
||||
|
||||
# Check status
|
||||
sudo systemctl status ppanel
|
||||
```
|
||||
|
||||
### Rollback
|
||||
|
||||
If upgrade fails:
|
||||
|
||||
```bash
|
||||
# Stop service
|
||||
sudo systemctl stop ppanel
|
||||
|
||||
# Restore old binaries
|
||||
sudo mv /opt/ppanel/ppanel-server.old /opt/ppanel/ppanel-server
|
||||
sudo mv /opt/ppanel/gateway.old /opt/ppanel/gateway
|
||||
|
||||
# Restore database (if needed)
|
||||
sudo cp /opt/ppanel/data/ppanel.db.backup-YYYYMMDD /opt/ppanel/data/ppanel.db
|
||||
|
||||
# Start service
|
||||
sudo systemctl start ppanel
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Service Fails to Start
|
||||
|
||||
```bash
|
||||
# Check detailed logs
|
||||
sudo journalctl -u ppanel -xe
|
||||
|
||||
# Check configuration syntax
|
||||
/opt/ppanel/ppanel-server --check-config
|
||||
|
||||
# Verify permissions
|
||||
ls -la /opt/ppanel
|
||||
sudo chown -R root:root /opt/ppanel
|
||||
```
|
||||
|
||||
### Port Already in Use
|
||||
|
||||
```bash
|
||||
# Find what's using the port
|
||||
sudo lsof -i :8080
|
||||
sudo netstat -tlnp | grep 8080
|
||||
|
||||
# Change port in configuration
|
||||
sudo nano /opt/ppanel/etc/ppanel.yaml
|
||||
# Update server.port value
|
||||
|
||||
# Restart service
|
||||
sudo systemctl restart ppanel
|
||||
```
|
||||
|
||||
### Binary Won't Execute
|
||||
|
||||
```bash
|
||||
# Check architecture compatibility
|
||||
uname -m
|
||||
file /opt/ppanel/ppanel-server
|
||||
|
||||
# Check if executable
|
||||
ls -la /opt/ppanel/ppanel-server
|
||||
sudo chmod +x /opt/ppanel/ppanel-server
|
||||
|
||||
# Check for missing libraries (should be none for static binary)
|
||||
ldd /opt/ppanel/ppanel-server
|
||||
```
|
||||
|
||||
### High Memory Usage
|
||||
|
||||
```bash
|
||||
# Check memory usage
|
||||
ps aux | grep ppanel
|
||||
top -p $(pgrep ppanel-server)
|
||||
|
||||
# Add memory limit to systemd service
|
||||
sudo nano /etc/systemd/system/ppanel.service
|
||||
# Add under [Service]:
|
||||
# MemoryMax=2G
|
||||
# MemoryHigh=1.5G
|
||||
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl restart ppanel
|
||||
```
|
||||
|
||||
### Database Connection Issues
|
||||
|
||||
```bash
|
||||
# Check database file permissions
|
||||
ls -la /opt/ppanel/data/
|
||||
|
||||
# For SQLite, verify path in config
|
||||
sudo nano /opt/ppanel/etc/ppanel.yaml
|
||||
|
||||
# Test database connection
|
||||
sqlite3 /opt/ppanel/data/ppanel.db "SELECT 1;"
|
||||
|
||||
# Check logs for database errors
|
||||
sudo journalctl -u ppanel | grep -i database
|
||||
```
|
||||
|
||||
## Uninstallation
|
||||
|
||||
To completely remove PPanel:
|
||||
|
||||
```bash
|
||||
# Stop and disable service
|
||||
sudo systemctl stop ppanel
|
||||
sudo systemctl disable ppanel
|
||||
|
||||
# Remove service file
|
||||
sudo rm /etc/systemd/system/ppanel.service
|
||||
sudo systemctl daemon-reload
|
||||
|
||||
# Remove installation directory
|
||||
sudo rm -rf /opt/ppanel
|
||||
|
||||
# Remove firewall rules (if added)
|
||||
sudo ufw delete allow 8080/tcp
|
||||
# or
|
||||
sudo firewall-cmd --permanent --remove-port=8080/tcp
|
||||
sudo firewall-cmd --reload
|
||||
```
|
||||
|
||||
## Advanced Configuration
|
||||
|
||||
### Running as Non-Root User
|
||||
|
||||
For better security, run as dedicated user:
|
||||
|
||||
```bash
|
||||
# Create dedicated user
|
||||
sudo useradd -r -s /bin/false ppanel
|
||||
|
||||
# Change ownership
|
||||
sudo chown -R ppanel:ppanel /opt/ppanel
|
||||
|
||||
# Update systemd service
|
||||
sudo nano /etc/systemd/system/ppanel.service
|
||||
# Change: User=ppanel
|
||||
|
||||
# If binding to port < 1024, grant capability
|
||||
sudo setcap 'cap_net_bind_service=+ep' /opt/ppanel/ppanel-server
|
||||
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl restart ppanel
|
||||
```
|
||||
|
||||
### Multiple Instances
|
||||
|
||||
To run multiple instances:
|
||||
|
||||
```bash
|
||||
# Create separate directories
|
||||
sudo mkdir -p /opt/ppanel-1
|
||||
sudo mkdir -p /opt/ppanel-2
|
||||
|
||||
# Copy binaries and configs
|
||||
sudo cp -r /opt/ppanel/* /opt/ppanel-1/
|
||||
sudo cp -r /opt/ppanel/* /opt/ppanel-2/
|
||||
|
||||
# Edit configs with different ports
|
||||
sudo nano /opt/ppanel-1/etc/ppanel.yaml # port: 8081
|
||||
sudo nano /opt/ppanel-2/etc/ppanel.yaml # port: 8082
|
||||
|
||||
# Create separate systemd services
|
||||
sudo cp /etc/systemd/system/ppanel.service /etc/systemd/system/ppanel-1.service
|
||||
sudo cp /etc/systemd/system/ppanel.service /etc/systemd/system/ppanel-2.service
|
||||
|
||||
# Edit service files accordingly
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable ppanel-1 ppanel-2
|
||||
sudo systemctl start ppanel-1 ppanel-2
|
||||
```
|
||||
|
||||
### Custom Environment Variables
|
||||
|
||||
Add environment variables to systemd service:
|
||||
|
||||
```ini
|
||||
[Service]
|
||||
Environment="PPANEL_ENV=production"
|
||||
Environment="PPANEL_DEBUG=false"
|
||||
EnvironmentFile=/opt/ppanel/env.conf
|
||||
```
|
||||
|
||||
## Performance Tuning
|
||||
|
||||
### Optimize File Limits
|
||||
|
||||
```bash
|
||||
# Edit limits
|
||||
sudo nano /etc/security/limits.conf
|
||||
|
||||
# Add:
|
||||
* soft nofile 65535
|
||||
* hard nofile 65535
|
||||
|
||||
# For systemd service, already set in service file:
|
||||
# LimitNOFILE=65535
|
||||
```
|
||||
|
||||
### Enable Database Optimization
|
||||
|
||||
For SQLite:
|
||||
|
||||
```bash
|
||||
# Add to ppanel.yaml
|
||||
database:
|
||||
type: sqlite
|
||||
path: /opt/ppanel/data/ppanel.db
|
||||
options:
|
||||
cache_size: -2000
|
||||
journal_mode: WAL
|
||||
synchronous: NORMAL
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
- [Configuration Guide](/guide/configuration) - Detailed configuration options
|
||||
- [Admin Dashboard](/admin/dashboard) - Start managing your panel
|
||||
- [API Reference](/api/reference) - API integration
|
||||
|
||||
## Need Help?
|
||||
|
||||
- Check [GitHub Issues](https://github.com/perfect-panel/ppanel/issues)
|
||||
- Review systemd logs: `sudo journalctl -u ppanel -f`
|
||||
- Check application logs: `tail -f /opt/ppanel/logs/ppanel.log`
|
||||
@@ -0,0 +1,443 @@
|
||||
# Docker Compose Deployment
|
||||
|
||||
Docker Compose is the recommended deployment method for production environments. It provides better service management, easier configuration, and simplified upgrades.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
### Install Docker
|
||||
|
||||
If you haven't installed Docker yet, please follow the official installation guide:
|
||||
|
||||
**Ubuntu/Debian:**
|
||||
```bash
|
||||
# Update package index
|
||||
sudo apt-get update
|
||||
|
||||
# Install required packages
|
||||
sudo apt-get install -y ca-certificates curl gnupg lsb-release
|
||||
|
||||
# Add Docker's official GPG key
|
||||
sudo mkdir -p /etc/apt/keyrings
|
||||
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
|
||||
|
||||
# Set up the repository
|
||||
echo \
|
||||
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
|
||||
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
|
||||
|
||||
# Install Docker Engine
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
|
||||
```
|
||||
|
||||
**CentOS/RHEL:**
|
||||
```bash
|
||||
# Install yum-utils
|
||||
sudo yum install -y yum-utils
|
||||
|
||||
# Add Docker repository
|
||||
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
|
||||
|
||||
# Install Docker Engine
|
||||
sudo yum install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
|
||||
|
||||
# Start Docker service
|
||||
sudo systemctl start docker
|
||||
sudo systemctl enable docker
|
||||
```
|
||||
|
||||
### Verify Installation
|
||||
|
||||
```bash
|
||||
# Check Docker version
|
||||
docker --version
|
||||
|
||||
# Check Docker Compose version
|
||||
docker compose version
|
||||
|
||||
# Test Docker installation
|
||||
sudo docker run hello-world
|
||||
```
|
||||
|
||||
## Deployment Steps
|
||||
|
||||
### Step 1: Create Project Directory
|
||||
|
||||
```bash
|
||||
# Create project directory
|
||||
mkdir -p ~/ppanel
|
||||
cd ~/ppanel
|
||||
```
|
||||
|
||||
### Step 2: Create docker-compose.yml
|
||||
|
||||
Create a `docker-compose.yml` file with the following content:
|
||||
|
||||
```yaml
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
ppanel:
|
||||
image: ppanel/ppanel:latest
|
||||
container_name: ppanel
|
||||
ports:
|
||||
- "8080:8080"
|
||||
volumes:
|
||||
- ./ppanel-config:/app/etc:ro
|
||||
- ppanel-data:/app/data
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- TZ=UTC
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:8080/health"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 40s
|
||||
|
||||
volumes:
|
||||
ppanel-data:
|
||||
driver: local
|
||||
```
|
||||
|
||||
**Configuration Explanation:**
|
||||
|
||||
- **image**: Docker image to use (latest or specific version like `v0.1.2`)
|
||||
- **ports**: Map container port 8080 to host port 8080
|
||||
- **volumes**:
|
||||
- `./ppanel-config:/app/etc:ro` - Configuration directory (read-only)
|
||||
- `ppanel-data:/app/data` - Persistent data storage
|
||||
- **restart**: Auto-restart policy
|
||||
- **environment**: Set timezone (change to your timezone like `Asia/Shanghai`)
|
||||
- **healthcheck**: Monitor service health
|
||||
|
||||
### Step 3: Prepare Configuration
|
||||
|
||||
```bash
|
||||
# Create configuration directory
|
||||
mkdir -p ppanel-config
|
||||
|
||||
# Create configuration file
|
||||
cat > ppanel-config/ppanel.yaml <<EOF
|
||||
# PPanel Configuration
|
||||
server:
|
||||
host: 0.0.0.0
|
||||
port: 8080
|
||||
|
||||
database:
|
||||
type: sqlite
|
||||
path: /app/data/ppanel.db
|
||||
|
||||
# Add more configuration as needed
|
||||
EOF
|
||||
```
|
||||
|
||||
::: tip
|
||||
For detailed configuration options, please refer to the [Configuration Guide](/guide/configuration).
|
||||
:::
|
||||
|
||||
### Step 4: Start Services
|
||||
|
||||
```bash
|
||||
# Pull the latest image
|
||||
docker compose pull
|
||||
|
||||
# Start in detached mode
|
||||
docker compose up -d
|
||||
|
||||
# View logs
|
||||
docker compose logs -f
|
||||
```
|
||||
|
||||
### Step 5: Verify Deployment
|
||||
|
||||
```bash
|
||||
# Check service status
|
||||
docker compose ps
|
||||
|
||||
# Check if service is accessible
|
||||
curl http://localhost:8080
|
||||
|
||||
# View real-time logs
|
||||
docker compose logs -f ppanel
|
||||
```
|
||||
|
||||
## Post-Installation
|
||||
|
||||
### Access the Application
|
||||
|
||||
After successful installation, you can access:
|
||||
|
||||
- **User Panel**: `http://your-server-ip:8080`
|
||||
- **Admin Panel**: `http://your-server-ip:8080/admin`
|
||||
|
||||
::: warning Default Credentials
|
||||
Please change the default admin password immediately after first login for security.
|
||||
:::
|
||||
|
||||
### Configure Reverse Proxy (Recommended)
|
||||
|
||||
For production deployment, it's recommended to use Nginx or Caddy as a reverse proxy to enable HTTPS.
|
||||
|
||||
**Nginx Configuration:**
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 80;
|
||||
server_name your-domain.com;
|
||||
|
||||
# Redirect to HTTPS
|
||||
return 301 https://$server_name$request_uri;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name your-domain.com;
|
||||
|
||||
ssl_certificate /path/to/your/certificate.crt;
|
||||
ssl_certificate_key /path/to/your/private.key;
|
||||
|
||||
location / {
|
||||
proxy_pass http://localhost:8080;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header X-Forwarded-Host $host;
|
||||
proxy_set_header X-Forwarded-Port $server_port;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Caddy Configuration:**
|
||||
|
||||
```
|
||||
your-domain.com {
|
||||
reverse_proxy localhost:8080
|
||||
}
|
||||
```
|
||||
|
||||
::: tip
|
||||
Caddy automatically handles SSL certificates via Let's Encrypt.
|
||||
:::
|
||||
|
||||
## Service Management
|
||||
|
||||
### View Logs
|
||||
|
||||
```bash
|
||||
# View all logs
|
||||
docker compose logs
|
||||
|
||||
# Follow logs in real-time
|
||||
docker compose logs -f
|
||||
|
||||
# View specific service logs
|
||||
docker compose logs ppanel
|
||||
```
|
||||
|
||||
### Stop Services
|
||||
|
||||
```bash
|
||||
# Stop all services
|
||||
docker compose stop
|
||||
|
||||
# Stop specific service
|
||||
docker compose stop ppanel
|
||||
```
|
||||
|
||||
### Restart Services
|
||||
|
||||
```bash
|
||||
# Restart all services
|
||||
docker compose restart
|
||||
|
||||
# Restart specific service
|
||||
docker compose restart ppanel
|
||||
```
|
||||
|
||||
### Stop and Remove Services
|
||||
|
||||
```bash
|
||||
# Stop and remove containers
|
||||
docker compose down
|
||||
|
||||
# Stop and remove containers and volumes
|
||||
docker compose down -v
|
||||
```
|
||||
|
||||
::: warning Data Persistence
|
||||
Using `docker compose down -v` will delete all data volumes. Only use this if you want to completely remove all data.
|
||||
:::
|
||||
|
||||
## Upgrading
|
||||
|
||||
### Backup Before Upgrade
|
||||
|
||||
```bash
|
||||
# Backup configuration
|
||||
tar czf ppanel-config-backup-$(date +%Y%m%d).tar.gz ppanel-config/
|
||||
|
||||
# Backup data volume
|
||||
docker run --rm \
|
||||
-v ppanel_ppanel-data:/data \
|
||||
-v $(pwd):/backup \
|
||||
alpine tar czf /backup/ppanel-data-backup-$(date +%Y%m%d).tar.gz /data
|
||||
```
|
||||
|
||||
### Upgrade Steps
|
||||
|
||||
```bash
|
||||
# Pull latest image
|
||||
docker compose pull
|
||||
|
||||
# Recreate containers with new image
|
||||
docker compose up -d
|
||||
|
||||
# View logs to verify
|
||||
docker compose logs -f
|
||||
```
|
||||
|
||||
### Rollback
|
||||
|
||||
If you encounter issues after upgrading:
|
||||
|
||||
```bash
|
||||
# Edit docker-compose.yml and change image to previous version
|
||||
# image: ppanel/ppanel:v0.1.1
|
||||
|
||||
# Restart with previous version
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
## Advanced Configuration
|
||||
|
||||
### Custom Port
|
||||
|
||||
To use a different port, edit `docker-compose.yml`:
|
||||
|
||||
```yaml
|
||||
ports:
|
||||
- "3000:8080" # Host port 3000 -> Container port 8080
|
||||
```
|
||||
|
||||
### Multiple Instances
|
||||
|
||||
To run multiple instances, create separate directories:
|
||||
|
||||
```bash
|
||||
# Instance 1
|
||||
mkdir ~/ppanel-1
|
||||
cd ~/ppanel-1
|
||||
# Create docker-compose.yml with port 8081
|
||||
|
||||
# Instance 2
|
||||
mkdir ~/ppanel-2
|
||||
cd ~/ppanel-2
|
||||
# Create docker-compose.yml with port 8082
|
||||
```
|
||||
|
||||
### Resource Limits
|
||||
|
||||
Add resource limits to prevent overconsumption:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
ppanel:
|
||||
# ... other config ...
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: '2'
|
||||
memory: 2G
|
||||
reservations:
|
||||
cpus: '0.5'
|
||||
memory: 512M
|
||||
```
|
||||
|
||||
### Custom Network
|
||||
|
||||
Create a custom network for better isolation:
|
||||
|
||||
```yaml
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
ppanel:
|
||||
# ... other config ...
|
||||
networks:
|
||||
- ppanel-net
|
||||
|
||||
networks:
|
||||
ppanel-net:
|
||||
driver: bridge
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Container Fails to Start
|
||||
|
||||
```bash
|
||||
# Check logs for errors
|
||||
docker compose logs ppanel
|
||||
|
||||
# Check container status
|
||||
docker compose ps
|
||||
|
||||
# Verify configuration
|
||||
docker compose config
|
||||
```
|
||||
|
||||
### Port Already in Use
|
||||
|
||||
```bash
|
||||
# Check what's using the port
|
||||
sudo lsof -i :8080
|
||||
|
||||
# Change port in docker-compose.yml
|
||||
# ports:
|
||||
# - "8081:8080"
|
||||
```
|
||||
|
||||
### Permission Issues
|
||||
|
||||
```bash
|
||||
# Fix configuration directory permissions
|
||||
sudo chown -R $USER:$USER ppanel-config/
|
||||
|
||||
# Make sure files are readable
|
||||
chmod 644 ppanel-config/ppanel.yaml
|
||||
```
|
||||
|
||||
### Cannot Access from Outside
|
||||
|
||||
1. **Check firewall rules:**
|
||||
```bash
|
||||
# Ubuntu/Debian
|
||||
sudo ufw allow 8080
|
||||
|
||||
# CentOS/RHEL
|
||||
sudo firewall-cmd --add-port=8080/tcp --permanent
|
||||
sudo firewall-cmd --reload
|
||||
```
|
||||
|
||||
2. **Verify service is listening:**
|
||||
```bash
|
||||
docker compose ps
|
||||
netstat -tlnp | grep 8080
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
- [Configuration Guide](/guide/configuration) - Detailed configuration options
|
||||
- [Admin Dashboard](/admin/dashboard) - Start managing your panel
|
||||
- [API Reference](/api/reference) - API integration guide
|
||||
|
||||
## Need Help?
|
||||
|
||||
If you encounter any issues:
|
||||
|
||||
1. Check the [Troubleshooting](#troubleshooting) section above
|
||||
2. Review [Docker Compose logs](#view-logs)
|
||||
3. Search [GitHub Issues](https://github.com/perfect-panel/ppanel/issues)
|
||||
4. Create a new issue with detailed system information and logs
|
||||
@@ -0,0 +1,348 @@
|
||||
# Docker Run Deployment
|
||||
|
||||
This guide shows you how to deploy PPanel using the `docker run` command. This method is suitable for quick testing or simple deployments.
|
||||
|
||||
::: tip
|
||||
For production environments, we recommend using [Docker Compose](/guide/installation/docker-compose) instead.
|
||||
:::
|
||||
|
||||
## Prerequisites
|
||||
|
||||
### Install Docker
|
||||
|
||||
**Ubuntu/Debian:**
|
||||
```bash
|
||||
# Update package index
|
||||
sudo apt-get update
|
||||
|
||||
# Install Docker
|
||||
sudo apt-get install -y ca-certificates curl gnupg lsb-release
|
||||
sudo mkdir -p /etc/apt/keyrings
|
||||
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
|
||||
|
||||
echo \
|
||||
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
|
||||
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
|
||||
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y docker-ce docker-ce-cli containerd.io
|
||||
```
|
||||
|
||||
**CentOS/RHEL:**
|
||||
```bash
|
||||
# Install Docker
|
||||
sudo yum install -y yum-utils
|
||||
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
|
||||
sudo yum install -y docker-ce docker-ce-cli containerd.io
|
||||
|
||||
# Start Docker
|
||||
sudo systemctl start docker
|
||||
sudo systemctl enable docker
|
||||
```
|
||||
|
||||
### Verify Installation
|
||||
|
||||
```bash
|
||||
docker --version
|
||||
sudo docker run hello-world
|
||||
```
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Step 1: Pull the Image
|
||||
|
||||
```bash
|
||||
# Pull latest version
|
||||
docker pull ppanel/ppanel:latest
|
||||
|
||||
# Or pull a specific version
|
||||
docker pull ppanel/ppanel:v0.1.2
|
||||
```
|
||||
|
||||
### Step 2: Prepare Configuration
|
||||
|
||||
```bash
|
||||
# Create configuration directory
|
||||
mkdir -p ~/ppanel-config
|
||||
|
||||
# Create configuration file
|
||||
cat > ~/ppanel-config/ppanel.yaml <<EOF
|
||||
server:
|
||||
host: 0.0.0.0
|
||||
port: 8080
|
||||
|
||||
database:
|
||||
type: sqlite
|
||||
path: /app/data/ppanel.db
|
||||
EOF
|
||||
```
|
||||
|
||||
### Step 3: Run Container
|
||||
|
||||
**Basic Command:**
|
||||
```bash
|
||||
docker run -d \
|
||||
--name ppanel \
|
||||
-p 8080:8080 \
|
||||
-v ~/ppanel-config:/app/etc:ro \
|
||||
-v ppanel-data:/app/data \
|
||||
--restart unless-stopped \
|
||||
ppanel/ppanel:latest
|
||||
```
|
||||
|
||||
**With All Options:**
|
||||
```bash
|
||||
docker run -d \
|
||||
--name ppanel \
|
||||
-p 8080:8080 \
|
||||
-v ~/ppanel-config:/app/etc:ro \
|
||||
-v ppanel-data:/app/data \
|
||||
-e TZ=UTC \
|
||||
--restart unless-stopped \
|
||||
--memory="2g" \
|
||||
--cpus="2" \
|
||||
ppanel/ppanel:latest
|
||||
```
|
||||
|
||||
**Parameter Explanation:**
|
||||
- `-d`: Run in detached mode (background)
|
||||
- `--name ppanel`: Set container name
|
||||
- `-p 8080:8080`: Map port (host:container)
|
||||
- `-v ~/ppanel-config:/app/etc:ro`: Mount configuration (read-only)
|
||||
- `-v ppanel-data:/app/data`: Create data volume
|
||||
- `-e TZ=UTC`: Set timezone
|
||||
- `--restart unless-stopped`: Auto-restart policy
|
||||
- `--memory="2g"`: Memory limit
|
||||
- `--cpus="2"`: CPU limit
|
||||
|
||||
### Step 4: Verify Running
|
||||
|
||||
```bash
|
||||
# Check container status
|
||||
docker ps | grep ppanel
|
||||
|
||||
# View logs
|
||||
docker logs -f ppanel
|
||||
|
||||
# Test access
|
||||
curl http://localhost:8080
|
||||
```
|
||||
|
||||
## Container Management
|
||||
|
||||
### View Logs
|
||||
|
||||
```bash
|
||||
# View all logs
|
||||
docker logs ppanel
|
||||
|
||||
# Follow logs in real-time
|
||||
docker logs -f ppanel
|
||||
|
||||
# View last 100 lines
|
||||
docker logs --tail 100 ppanel
|
||||
|
||||
# View logs with timestamps
|
||||
docker logs -t ppanel
|
||||
```
|
||||
|
||||
### Stop Container
|
||||
|
||||
```bash
|
||||
docker stop ppanel
|
||||
```
|
||||
|
||||
### Start Container
|
||||
|
||||
```bash
|
||||
docker start ppanel
|
||||
```
|
||||
|
||||
### Restart Container
|
||||
|
||||
```bash
|
||||
docker restart ppanel
|
||||
```
|
||||
|
||||
### Remove Container
|
||||
|
||||
```bash
|
||||
# Stop and remove
|
||||
docker stop ppanel
|
||||
docker rm ppanel
|
||||
```
|
||||
|
||||
::: warning
|
||||
Removing the container does not delete the data volume. To remove the volume:
|
||||
```bash
|
||||
docker volume rm ppanel-data
|
||||
```
|
||||
:::
|
||||
|
||||
## Upgrading
|
||||
|
||||
### Backup Data
|
||||
|
||||
```bash
|
||||
# Backup configuration
|
||||
tar czf ppanel-config-backup-$(date +%Y%m%d).tar.gz ~/ppanel-config/
|
||||
|
||||
# Backup data volume
|
||||
docker run --rm \
|
||||
-v ppanel-data:/data \
|
||||
-v $(pwd):/backup \
|
||||
alpine tar czf /backup/ppanel-data-backup-$(date +%Y%m%d).tar.gz /data
|
||||
```
|
||||
|
||||
### Upgrade Process
|
||||
|
||||
```bash
|
||||
# Pull latest image
|
||||
docker pull ppanel/ppanel:latest
|
||||
|
||||
# Stop old container
|
||||
docker stop ppanel
|
||||
|
||||
# Remove old container
|
||||
docker rm ppanel
|
||||
|
||||
# Start new container with same configuration
|
||||
docker run -d \
|
||||
--name ppanel \
|
||||
-p 8080:8080 \
|
||||
-v ~/ppanel-config:/app/etc:ro \
|
||||
-v ppanel-data:/app/data \
|
||||
--restart unless-stopped \
|
||||
ppanel/ppanel:latest
|
||||
|
||||
# Verify
|
||||
docker logs -f ppanel
|
||||
```
|
||||
|
||||
## Advanced Usage
|
||||
|
||||
### Custom Network
|
||||
|
||||
```bash
|
||||
# Create network
|
||||
docker network create ppanel-net
|
||||
|
||||
# Run with custom network
|
||||
docker run -d \
|
||||
--name ppanel \
|
||||
--network ppanel-net \
|
||||
-p 8080:8080 \
|
||||
-v ~/ppanel-config:/app/etc:ro \
|
||||
-v ppanel-data:/app/data \
|
||||
ppanel/ppanel:latest
|
||||
```
|
||||
|
||||
### Environment Variables
|
||||
|
||||
```bash
|
||||
docker run -d \
|
||||
--name ppanel \
|
||||
-p 8080:8080 \
|
||||
-e SERVER_PORT=8080 \
|
||||
-e DATABASE_TYPE=sqlite \
|
||||
-e TZ=Asia/Shanghai \
|
||||
-v ~/ppanel-config:/app/etc:ro \
|
||||
-v ppanel-data:/app/data \
|
||||
ppanel/ppanel:latest
|
||||
```
|
||||
|
||||
### Multiple Instances
|
||||
|
||||
```bash
|
||||
# Instance 1 on port 8081
|
||||
docker run -d \
|
||||
--name ppanel-1 \
|
||||
-p 8081:8080 \
|
||||
-v ~/ppanel-config-1:/app/etc:ro \
|
||||
-v ppanel-data-1:/app/data \
|
||||
ppanel/ppanel:latest
|
||||
|
||||
# Instance 2 on port 8082
|
||||
docker run -d \
|
||||
--name ppanel-2 \
|
||||
-p 8082:8080 \
|
||||
-v ~/ppanel-config-2:/app/etc:ro \
|
||||
-v ppanel-data-2:/app/data \
|
||||
ppanel/ppanel:latest
|
||||
```
|
||||
|
||||
### Resource Limits
|
||||
|
||||
```bash
|
||||
docker run -d \
|
||||
--name ppanel \
|
||||
-p 8080:8080 \
|
||||
--memory="2g" \
|
||||
--memory-swap="2g" \
|
||||
--cpus="2" \
|
||||
--pids-limit=100 \
|
||||
-v ~/ppanel-config:/app/etc:ro \
|
||||
-v ppanel-data:/app/data \
|
||||
ppanel/ppanel:latest
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Container Exits Immediately
|
||||
|
||||
```bash
|
||||
# Check logs
|
||||
docker logs ppanel
|
||||
|
||||
# Check architecture
|
||||
uname -m
|
||||
docker image inspect ppanel/ppanel:latest --format '{{.Architecture}}'
|
||||
```
|
||||
|
||||
### Port Already in Use
|
||||
|
||||
```bash
|
||||
# Check what's using the port
|
||||
sudo lsof -i :8080
|
||||
|
||||
# Use different port
|
||||
docker run -d --name ppanel -p 8081:8080 ...
|
||||
```
|
||||
|
||||
### Configuration Not Loading
|
||||
|
||||
```bash
|
||||
# Verify mount
|
||||
docker exec ppanel ls -la /app/etc
|
||||
|
||||
# Check file content
|
||||
docker exec ppanel cat /app/etc/ppanel.yaml
|
||||
|
||||
# Check permissions
|
||||
ls -la ~/ppanel-config/
|
||||
```
|
||||
|
||||
### Access Container Shell
|
||||
|
||||
```bash
|
||||
# Access bash (if available)
|
||||
docker exec -it ppanel bash
|
||||
|
||||
# Access sh
|
||||
docker exec -it ppanel sh
|
||||
|
||||
# Run command
|
||||
docker exec ppanel ls -la /app
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
- Try [Docker Compose](/guide/installation/docker-compose) for easier management
|
||||
- Configure [Reverse Proxy](/guide/installation/docker-compose#configure-reverse-proxy)
|
||||
- Learn about [Configuration](/guide/configuration)
|
||||
|
||||
## Need Help?
|
||||
|
||||
- Check [GitHub Issues](https://github.com/perfect-panel/ppanel/issues)
|
||||
- Review Docker logs: `docker logs ppanel`
|
||||
- Verify system requirements
|
||||
@@ -0,0 +1,57 @@
|
||||
# Installation Overview
|
||||
|
||||
PPanel supports multiple deployment methods to suit different needs and environments. Choose the method that best fits your requirements.
|
||||
|
||||
## Deployment Methods
|
||||
|
||||
### Docker Deployment (Recommended)
|
||||
|
||||
The easiest and most reliable way to deploy PPanel. Docker ensures consistent environments and simplifies updates.
|
||||
|
||||
- **[Docker Run](/guide/installation/docker-run)** - Quick deployment with a single command
|
||||
- **[Docker Compose](/guide/installation/docker-compose)** - Production-ready deployment with better management
|
||||
|
||||
### Traditional Deployment
|
||||
|
||||
- **[Binary Deployment](/guide/installation/binary)** - Deploy using pre-built binaries with systemd service
|
||||
|
||||
### Advanced Deployment
|
||||
|
||||
- **[Kubernetes](/guide/installation/kubernetes)** - Deploy PPanel in Kubernetes clusters for high availability
|
||||
- **[From Source](/guide/installation/from-source)** - Build and run PPanel from source code
|
||||
|
||||
## System Requirements
|
||||
|
||||
### Minimum Requirements
|
||||
- **Operating System**: Linux (Ubuntu 20.04+, Debian 10+, CentOS 8+)
|
||||
- **CPU**: 1 core
|
||||
- **Memory**: 512MB RAM
|
||||
- **Storage**: 1GB available disk space
|
||||
|
||||
### Recommended Requirements
|
||||
- **CPU**: 2+ cores
|
||||
- **Memory**: 2GB+ RAM
|
||||
- **Storage**: 5GB+ available disk space
|
||||
|
||||
## Prerequisites
|
||||
|
||||
All deployment methods require:
|
||||
- Linux-based operating system
|
||||
- Basic command line knowledge
|
||||
- Network access for downloading packages/images
|
||||
|
||||
Specific prerequisites vary by deployment method - check the individual guides for details.
|
||||
|
||||
## Quick Start
|
||||
|
||||
For most users, we recommend starting with Docker Compose:
|
||||
|
||||
1. [Install Docker and Docker Compose](/guide/installation/docker-compose#prerequisites)
|
||||
2. [Download configuration files](/guide/installation/docker-compose#download-configuration)
|
||||
3. [Start the services](/guide/installation/docker-compose#start-services)
|
||||
|
||||
## Need Help?
|
||||
|
||||
- Check our [Troubleshooting Guide](/guide/troubleshooting)
|
||||
- Visit [GitHub Issues](https://github.com/perfect-panel/ppanel/issues)
|
||||
- Join our community discussions
|
||||
@@ -0,0 +1,93 @@
|
||||
# Introduction
|
||||
|
||||
Welcome to PPanel! This is a pure, professional, and perfect open-source proxy panel tool designed to provide users with a complete management solution.
|
||||
|
||||
## What is PPanel?
|
||||
|
||||
PPanel is a modern proxy panel system that uses a separated frontend-backend architecture, providing complete user management, subscription services, order management, node management, and more. Whether you're an individual or enterprise user, PPanel can meet your needs.
|
||||
|
||||
## Core Features
|
||||
|
||||
- **🎯 Complete Management**: Server management, node configuration, subscription system, product management and more
|
||||
- **💼 Business Operations**: Order management, coupon system, marketing campaigns, announcement publishing
|
||||
- **👥 User Support System**: User management, ticket system, documentation center for comprehensive user service
|
||||
- **📊 Data Analytics**: 12 types of logs with comprehensive traffic, balance, commission data analysis
|
||||
- **🔧 Flexible Configuration**: Payment config, authentication control, ad management and flexible system options
|
||||
- **🚀 Modern Tech Stack**: Built with React 19 + TypeScript + TailwindCSS + shadcn/ui
|
||||
|
||||
## Terminology
|
||||
|
||||
Some of PPanel's terminology differs from other panel systems. To ensure accurate understanding and avoid confusion, please familiarize yourself with the following terms before reading the documentation:
|
||||
|
||||
### User Frontend
|
||||
The interface provided to end users, through which users interact with the system. You can customize or refactor this interface according to your needs to achieve site personalization.
|
||||
|
||||
### Admin Frontend
|
||||
The interface for administrator operations, responsible for managing the system, users, and data. You can customize or refactor this interface according to your management needs.
|
||||
|
||||
### Backend Server
|
||||
PPanel's API layer that handles all data interactions with the frontend, responsible for executing business logic and providing data services.
|
||||
|
||||
### Node Server
|
||||
Responsible for communication between PPanel's backend server and various nodes (landing points), ensuring network node connectivity and service stability.
|
||||
|
||||
### Client
|
||||
The application program users use to connect to the system, typically referring to user device software or applications, responsible for establishing connections with the system and using related services.
|
||||
|
||||
## Project Architecture
|
||||
|
||||
PPanel uses Monorepo architecture for unified management and maintenance:
|
||||
|
||||
### Frontend Applications
|
||||
- **apps/admin**: Admin panel application providing complete backend management features
|
||||
- **apps/user**: User-facing application providing service interface for end users
|
||||
|
||||
### Shared Packages
|
||||
- **packages/ui**: Shared UI component library containing all reusable UI components
|
||||
- **packages/typescript-config**: Unified TypeScript configuration
|
||||
|
||||
### Tech Stack
|
||||
- **Framework**: React 19 + TypeScript
|
||||
- **Router**: TanStack Router
|
||||
- **State Management**: Zustand
|
||||
- **Styling**: TailwindCSS 4.0
|
||||
- **UI Components**: shadcn/ui
|
||||
- **Build Tools**: Vite + Turbo
|
||||
- **Code Standards**: Biome
|
||||
- **Git Standards**: Lefthook + Gitmoji
|
||||
|
||||
## Key Features
|
||||
|
||||
### Maintenance
|
||||
- Server Management
|
||||
- Node Management
|
||||
- Subscribe Configuration
|
||||
- Product Management
|
||||
|
||||
### Commerce
|
||||
- Order Management
|
||||
- Coupon Management
|
||||
- Marketing Management
|
||||
- Announcement Management
|
||||
|
||||
### Users & Support
|
||||
- User Management
|
||||
- Ticket System
|
||||
- Document Management
|
||||
|
||||
### System
|
||||
- System Configuration
|
||||
- Authentication Control
|
||||
- Payment Configuration
|
||||
- ADS Configuration
|
||||
|
||||
### Logs & Analytics
|
||||
- Complete operation logs
|
||||
- Traffic statistics
|
||||
- Financial data tracking
|
||||
|
||||
## Next Steps
|
||||
|
||||
- [Installation](/guide/installation/) - Learn how to deploy PPanel
|
||||
- [Configuration](/guide/configuration) - Configure your PPanel instance
|
||||
- [Admin Panel](/admin/dashboard) - Start using admin features
|
||||
@@ -0,0 +1,168 @@
|
||||
# Node Agent Installation
|
||||
|
||||
`ppanel-node` is the lightweight agent each edge server runs to sync routes, heartbeats, and transport keys with the PPanel control plane. This guide covers the fastest install path plus alternative deployments.
|
||||
|
||||
## Quick start
|
||||
|
||||
```bash
|
||||
wget -N https://raw.githubusercontent.com/perfect-panel/ppanel-node/master/scripts/install.sh
|
||||
sudo bash install.sh --api-host https://panel.example.com --server-id 1 --secret-key <SECRET>
|
||||
```
|
||||
|
||||
The script auto-detects your distro/architecture, downloads the latest release, installs geo databases, and sets up the `ppnode` CLI + system service.
|
||||
|
||||
### Requirements
|
||||
|
||||
- 64-bit Linux (Debian/Ubuntu ≥16, CentOS ≥7, Alpine, Arch, etc.)
|
||||
- Root access and outbound HTTPS connectivity to `github.com`
|
||||
- Firewall ports open for the protocols you expose as well as panel callbacks
|
||||
- Matching **Server ID** + **Secret Key** generated in the PPanel admin console
|
||||
|
||||
### Optional flags
|
||||
|
||||
- Positional `vX.Y.Z` argument installs a specific tag instead of the latest release.
|
||||
- `--api-host https://panel.example.com`
|
||||
- `--server-id <ID>` (matches the record you created under Maintenance → Servers)
|
||||
- `--secret-key <KEY>`
|
||||
|
||||
If the flags are omitted the installer will prompt for the values interactively.
|
||||
|
||||
### Service operations
|
||||
|
||||
Once installed you can manage the agent with the bundled CLI:
|
||||
|
||||
```bash
|
||||
ppnode status # current state
|
||||
ppnode start # start daemon
|
||||
ppnode restart # restart + reload config
|
||||
ppnode log # follow logs
|
||||
ppnode update # upgrade to latest release
|
||||
ppnode update v1.2.3
|
||||
ppnode uninstall
|
||||
ppnode generate # regenerate /etc/PPanel-node/config.yml
|
||||
```
|
||||
|
||||
## Installation methods
|
||||
|
||||
### Method 1 — One-click installer (recommended)
|
||||
|
||||
Use the Quick Start command above or run `sudo bash install.sh` and answer the prompts. Behind the scenes the script:
|
||||
|
||||
1. Installs prerequisites (`wget`, `curl`, `tar`, `socat`, cron, etc.).
|
||||
2. Downloads `ppanel-node-linux-<arch>.zip` for amd64, arm64, or s390x.
|
||||
3. Extracts to `/usr/local/PPanel-node`, installs `geoip.dat`/`geosite.dat`, and wires the service with systemd/OpenRC.
|
||||
4. Drops the helper CLI to `/usr/bin/ppnode` and enables auto-start.
|
||||
|
||||
### Method 2 — Build from source
|
||||
|
||||
1. Install Go 1.21 or newer and enable the JSON v2 experiment:
|
||||
|
||||
```bash
|
||||
export GOEXPERIMENT=jsonv2
|
||||
```
|
||||
|
||||
2. Clone the repository and build:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/perfect-panel/ppanel-node.git
|
||||
cd ppanel-node
|
||||
GOEXPERIMENT=jsonv2 go build -v -o ./ppnode -trimpath -ldflags "-s -w -buildid="
|
||||
```
|
||||
|
||||
3. Copy the binary plus geo assets to their runtime locations:
|
||||
|
||||
```bash
|
||||
sudo install -Dm755 ./ppnode /usr/local/PPanel-node/ppnode
|
||||
sudo install -Dm644 ./geoip.dat /etc/PPanel-node/geoip.dat
|
||||
sudo install -Dm644 ./geosite.dat /etc/PPanel-node/geosite.dat
|
||||
```
|
||||
|
||||
4. Create the systemd unit (adapt paths as needed):
|
||||
|
||||
```bash
|
||||
sudo tee /etc/systemd/system/PPanel-node.service <<'EOF'
|
||||
[Unit]
|
||||
Description=PPanel Node
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=/usr/local/PPanel-node/ppnode server
|
||||
Restart=always
|
||||
RestartSec=10
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable --now PPanel-node
|
||||
```
|
||||
|
||||
5. Copy `config.yml` from the repo or create it manually (see the configuration section) and restart the service.
|
||||
|
||||
### Method 3 — Docker / container images
|
||||
|
||||
The repository ships a `Dockerfile`. You can build and run it on hosts where installing directly is undesirable:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/perfect-panel/ppanel-node.git
|
||||
cd ppanel-node
|
||||
docker build -t ppanel-node:latest .
|
||||
docker run -d --name ppanel-node \
|
||||
--net host \
|
||||
-v /etc/PPanel-node:/etc/PPanel-node \
|
||||
ppanel-node:latest server
|
||||
```
|
||||
|
||||
Recommended bind mounts:
|
||||
|
||||
- `/etc/PPanel-node/config.yml` – credentials and API settings.
|
||||
- `/etc/PPanel-node/geoip.dat` & `/etc/PPanel-node/geosite.dat` – keep them on the host so updates persist.
|
||||
- `/var/log/ppanel-node` (optional) – collect structured logs outside the container.
|
||||
|
||||
## Configure the node
|
||||
|
||||
The runtime configuration lives in `/etc/PPanel-node/config.yml`. The installer generates the file with the following structure:
|
||||
|
||||
```yaml
|
||||
Log:
|
||||
Level: warn # debug | info | warn | error
|
||||
Output: "" # empty = stdout, or set a file path
|
||||
Access: none # path for access logs, or "none"
|
||||
|
||||
Api:
|
||||
ApiHost: https://panel.example.com
|
||||
ServerID: 3
|
||||
SecretKey: b23d8ee1cfe44d7f
|
||||
Timeout: 30
|
||||
```
|
||||
|
||||
After editing the file, restart the service:
|
||||
|
||||
```bash
|
||||
sudo systemctl restart PPanel-node
|
||||
# or
|
||||
ppnode restart
|
||||
```
|
||||
|
||||
### Mapping to the panel
|
||||
|
||||
1. Create a server entry in the **Maintenance → Servers** page inside the PPanel admin UI.
|
||||
2. Copy the generated **Server ID** and **Secret Key** into `config.yml`.
|
||||
3. Ensure the node host can reach the panel’s HTTPS endpoint defined as `ApiHost`.
|
||||
4. Approve the node once it appears under the panel’s node list (heartbeat should update within ~30 seconds).
|
||||
|
||||
## Maintenance
|
||||
|
||||
- `ppnode update` keeps configuration/geo files intact while replacing the binary.
|
||||
- `ppnode update vX.Y.Z` pins a specific release for rollbacks.
|
||||
- For manual builds, rebuild the target tag, replace `/usr/local/PPanel-node/ppnode`, then `systemctl restart PPanel-node`.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- `ppnode log` or `journalctl -u PPanel-node -f` surfaces runtime logs.
|
||||
- Validate `/etc/PPanel-node/config.yml`—typos in `ApiHost` or `SecretKey` cause auth failures.
|
||||
- Ensure the host can reach GitHub (updates) and your panel domain on port 443.
|
||||
- If the panel lists the node as offline, verify firewall rules allow heartbeats and that NTP is synchronized (`chronyc tracking`).
|
||||
|
||||
Need more detail? Review the source at [`github.com/perfect-panel/ppanel-node`](https://github.com/perfect-panel/ppanel-node).
|
||||
@@ -0,0 +1,505 @@
|
||||
# Backend Separation Deployment
|
||||
|
||||
This guide will help you independently deploy the PPanel backend service, suitable for front-end and back-end separation deployment scenarios.
|
||||
|
||||
## Overview
|
||||
|
||||
Backend separation deployment allows you to deploy the PPanel backend service on an independent server to provide API services for frontend applications. This deployment method has the following advantages:
|
||||
|
||||
- 🚀 Independently scale backend service performance
|
||||
- 🔒 Better security isolation
|
||||
- 🌐 Support multiple frontend instances connecting to the same backend
|
||||
- 🛠️ Facilitate independent maintenance and upgrades of backend services
|
||||
|
||||
## System Requirements
|
||||
|
||||
### Minimum Configuration
|
||||
- CPU: 1 core
|
||||
- Memory: 1 GB
|
||||
- Storage: 10 GB
|
||||
- OS: Linux (Ubuntu 20.04+, Debian 11+, CentOS 8+ recommended)
|
||||
|
||||
### Recommended Configuration
|
||||
- CPU: 2+ cores
|
||||
- Memory: 2+ GB
|
||||
- Storage: 20+ GB
|
||||
|
||||
## Deployment Methods
|
||||
|
||||
### Method 1: Docker Deployment (Recommended)
|
||||
|
||||
#### 1. Install Docker
|
||||
|
||||
```bash
|
||||
# Ubuntu/Debian
|
||||
curl -fsSL https://get.docker.com | sh
|
||||
|
||||
# Start Docker service
|
||||
sudo systemctl start docker
|
||||
sudo systemctl enable docker
|
||||
```
|
||||
|
||||
#### 2. Create Configuration File
|
||||
|
||||
Create backend config file `config.yaml`:
|
||||
|
||||
```yaml
|
||||
# Database configuration
|
||||
database:
|
||||
type: mysql
|
||||
host: localhost
|
||||
port: 3306
|
||||
username: ppanel
|
||||
password: your_password
|
||||
database: ppanel
|
||||
|
||||
# Redis configuration
|
||||
redis:
|
||||
host: localhost
|
||||
port: 6379
|
||||
password: ""
|
||||
db: 0
|
||||
|
||||
# Server configuration
|
||||
server:
|
||||
host: 0.0.0.0
|
||||
port: 8080
|
||||
|
||||
# CORS configuration (Important: allow frontend domain access)
|
||||
cors:
|
||||
allow_origins:
|
||||
- "https://your-frontend-domain.com"
|
||||
- "http://localhost:3000" # Development environment
|
||||
allow_methods:
|
||||
- GET
|
||||
- POST
|
||||
- PUT
|
||||
- DELETE
|
||||
- OPTIONS
|
||||
allow_headers:
|
||||
- "*"
|
||||
|
||||
# JWT configuration
|
||||
jwt:
|
||||
secret: "your-secret-key"
|
||||
expire: 7200 # 2 hours
|
||||
|
||||
# API configuration
|
||||
api:
|
||||
prefix: "/api"
|
||||
version: "v1"
|
||||
```
|
||||
|
||||
#### 3. Prepare MySQL Database
|
||||
|
||||
```bash
|
||||
# Run MySQL with Docker
|
||||
docker run -d \
|
||||
--name ppanel-mysql \
|
||||
-e MYSQL_ROOT_PASSWORD=root_password \
|
||||
-e MYSQL_DATABASE=ppanel \
|
||||
-e MYSQL_USER=ppanel \
|
||||
-e MYSQL_PASSWORD=your_password \
|
||||
-p 3306:3306 \
|
||||
-v ppanel-mysql-data:/var/lib/mysql \
|
||||
mysql:8.0
|
||||
|
||||
# Wait for MySQL to start
|
||||
sleep 10
|
||||
```
|
||||
|
||||
#### 4. Prepare Redis
|
||||
|
||||
```bash
|
||||
# Run Redis with Docker
|
||||
docker run -d \
|
||||
--name ppanel-redis \
|
||||
-p 6379:6379 \
|
||||
-v ppanel-redis-data:/data \
|
||||
redis:7-alpine
|
||||
```
|
||||
|
||||
#### 5. Run Backend Service
|
||||
|
||||
```bash
|
||||
# Pull backend image
|
||||
docker pull ghcr.io/perfect-panel/ppanel:latest
|
||||
|
||||
# Run backend container
|
||||
docker run -d \
|
||||
--name ppanel-backend \
|
||||
-p 8080:8080 \
|
||||
-v $(pwd)/config.yaml:/app/config.yaml \
|
||||
--link ppanel-mysql:mysql \
|
||||
--link ppanel-redis:redis \
|
||||
ghcr.io/perfect-panel/ppanel:latest
|
||||
```
|
||||
|
||||
#### 6. Initialize Database
|
||||
|
||||
```bash
|
||||
# Execute database migration
|
||||
docker exec ppanel-backend ./ppanel migrate
|
||||
```
|
||||
|
||||
### Method 2: Binary Deployment
|
||||
|
||||
#### 1. Download Backend Program
|
||||
|
||||
```bash
|
||||
# Download latest version
|
||||
wget https://github.com/perfect-panel/ppanel/releases/latest/download/ppanel-linux-amd64.tar.gz
|
||||
|
||||
# Extract
|
||||
tar -xzf ppanel-linux-amd64.tar.gz
|
||||
cd ppanel
|
||||
|
||||
# Grant execute permission
|
||||
chmod +x ppanel
|
||||
```
|
||||
|
||||
#### 2. Configure Backend Service
|
||||
|
||||
Create config file `config.yaml` (same content as Docker deployment method).
|
||||
|
||||
#### 3. Install and Configure MySQL
|
||||
|
||||
```bash
|
||||
# Ubuntu/Debian
|
||||
sudo apt update
|
||||
sudo apt install mysql-server -y
|
||||
|
||||
# Create database and user
|
||||
sudo mysql <<EOF
|
||||
CREATE DATABASE ppanel;
|
||||
CREATE USER 'ppanel'@'localhost' IDENTIFIED BY 'your_password';
|
||||
GRANT ALL PRIVILEGES ON ppanel.* TO 'ppanel'@'localhost';
|
||||
FLUSH PRIVILEGES;
|
||||
EOF
|
||||
```
|
||||
|
||||
#### 4. Install and Configure Redis
|
||||
|
||||
```bash
|
||||
# Ubuntu/Debian
|
||||
sudo apt install redis-server -y
|
||||
sudo systemctl start redis-server
|
||||
sudo systemctl enable redis-server
|
||||
```
|
||||
|
||||
#### 5. Initialize Database
|
||||
|
||||
```bash
|
||||
# Execute database migration
|
||||
./ppanel migrate
|
||||
```
|
||||
|
||||
#### 6. Create systemd Service
|
||||
|
||||
Create service file `/etc/systemd/system/ppanel.service`:
|
||||
|
||||
```ini
|
||||
[Unit]
|
||||
Description=PPanel Backend Service
|
||||
After=network.target mysql.service redis.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=ppanel
|
||||
WorkingDirectory=/opt/ppanel
|
||||
ExecStart=/opt/ppanel/ppanel server
|
||||
Restart=on-failure
|
||||
RestartSec=5s
|
||||
StandardOutput=journal
|
||||
StandardError=journal
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
Start service:
|
||||
|
||||
```bash
|
||||
# Create dedicated user
|
||||
sudo useradd -r -s /bin/false ppanel
|
||||
|
||||
# Move files to installation directory
|
||||
sudo mkdir -p /opt/ppanel
|
||||
sudo mv ppanel config.yaml /opt/ppanel/
|
||||
sudo chown -R ppanel:ppanel /opt/ppanel
|
||||
|
||||
# Start service
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl start ppanel
|
||||
sudo systemctl enable ppanel
|
||||
|
||||
# Check service status
|
||||
sudo systemctl status ppanel
|
||||
```
|
||||
|
||||
## Configure Reverse Proxy
|
||||
|
||||
### Nginx Configuration
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 80;
|
||||
server_name api.your-domain.com;
|
||||
|
||||
# HTTPS redirect (recommended to configure SSL certificate)
|
||||
# return 301 https://$server_name$request_uri;
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:8080;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
|
||||
# WebSocket support
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
|
||||
# Timeout configuration
|
||||
proxy_connect_timeout 60s;
|
||||
proxy_send_timeout 60s;
|
||||
proxy_read_timeout 60s;
|
||||
}
|
||||
}
|
||||
|
||||
# HTTPS configuration example
|
||||
# server {
|
||||
# listen 443 ssl http2;
|
||||
# server_name api.your-domain.com;
|
||||
#
|
||||
# ssl_certificate /path/to/cert.pem;
|
||||
# ssl_certificate_key /path/to/key.pem;
|
||||
#
|
||||
# location / {
|
||||
# proxy_pass http://127.0.0.1:8080;
|
||||
# # ... other configs same as above
|
||||
# }
|
||||
# }
|
||||
```
|
||||
|
||||
Reload Nginx:
|
||||
|
||||
```bash
|
||||
sudo nginx -t
|
||||
sudo systemctl reload nginx
|
||||
```
|
||||
|
||||
### Caddy Configuration
|
||||
|
||||
```caddy
|
||||
api.your-domain.com {
|
||||
reverse_proxy localhost:8080
|
||||
}
|
||||
```
|
||||
|
||||
## Verify Deployment
|
||||
|
||||
### Health Check
|
||||
|
||||
```bash
|
||||
# Check if backend service is running
|
||||
curl http://localhost:8080/api/health
|
||||
|
||||
# Expected output
|
||||
# {"status":"ok","version":"1.0.0"}
|
||||
```
|
||||
|
||||
### Test API
|
||||
|
||||
```bash
|
||||
# Test public API
|
||||
curl http://localhost:8080/api/v1/ping
|
||||
|
||||
# Expected output
|
||||
# {"message":"pong"}
|
||||
```
|
||||
|
||||
## Environment Variable Configuration
|
||||
|
||||
Besides config file, you can also use environment variables:
|
||||
|
||||
```bash
|
||||
# Database configuration
|
||||
export DB_HOST=localhost
|
||||
export DB_PORT=3306
|
||||
export DB_USER=ppanel
|
||||
export DB_PASSWORD=your_password
|
||||
export DB_NAME=ppanel
|
||||
|
||||
# Redis configuration
|
||||
export REDIS_HOST=localhost
|
||||
export REDIS_PORT=6379
|
||||
export REDIS_PASSWORD=""
|
||||
|
||||
# JWT secret
|
||||
export JWT_SECRET=your-secret-key
|
||||
|
||||
# Server port
|
||||
export SERVER_PORT=8080
|
||||
```
|
||||
|
||||
Using environment variables with Docker:
|
||||
|
||||
```bash
|
||||
docker run -d \
|
||||
--name ppanel-backend \
|
||||
-p 8080:8080 \
|
||||
-e DB_HOST=mysql \
|
||||
-e DB_USER=ppanel \
|
||||
-e DB_PASSWORD=your_password \
|
||||
-e REDIS_HOST=redis \
|
||||
--link ppanel-mysql:mysql \
|
||||
--link ppanel-redis:redis \
|
||||
ghcr.io/perfect-panel/ppanel:latest
|
||||
```
|
||||
|
||||
## Security Recommendations
|
||||
|
||||
1. **Use Strong Passwords**: Set strong passwords for database and JWT secret
|
||||
2. **Configure Firewall**: Only open necessary ports (e.g., 80, 443)
|
||||
3. **Enable HTTPS**: Use SSL/TLS certificates to encrypt communication
|
||||
4. **CORS Configuration**: Only allow trusted frontend domains
|
||||
5. **Regular Backups**: Regularly backup database and config files
|
||||
6. **Monitor Logs**: Regularly check application and system logs
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Service Failed to Start
|
||||
|
||||
```bash
|
||||
# View service logs
|
||||
sudo journalctl -u ppanel -n 50 --no-pager
|
||||
|
||||
# Docker view logs
|
||||
docker logs ppanel-backend
|
||||
```
|
||||
|
||||
### Database Connection Failed
|
||||
|
||||
```bash
|
||||
# Test MySQL connection
|
||||
mysql -h localhost -u ppanel -p -e "SELECT 1;"
|
||||
|
||||
# Check MySQL service status
|
||||
sudo systemctl status mysql
|
||||
```
|
||||
|
||||
### Redis Connection Failed
|
||||
|
||||
```bash
|
||||
# Test Redis connection
|
||||
redis-cli ping
|
||||
|
||||
# Check Redis service status
|
||||
sudo systemctl status redis-server
|
||||
```
|
||||
|
||||
### CORS Error
|
||||
|
||||
Ensure frontend domain is correctly configured in `config.yaml`:
|
||||
|
||||
```yaml
|
||||
cors:
|
||||
allow_origins:
|
||||
- "https://your-frontend-domain.com"
|
||||
```
|
||||
|
||||
## Performance Optimization
|
||||
|
||||
### Database Optimization
|
||||
|
||||
```sql
|
||||
-- Create necessary indexes
|
||||
CREATE INDEX idx_user_email ON users(email);
|
||||
CREATE INDEX idx_order_status ON orders(status);
|
||||
CREATE INDEX idx_created_at ON orders(created_at);
|
||||
```
|
||||
|
||||
### Redis Cache Configuration
|
||||
|
||||
```yaml
|
||||
redis:
|
||||
# Enable cache
|
||||
cache_enabled: true
|
||||
# Cache expiration time (seconds)
|
||||
cache_ttl: 3600
|
||||
```
|
||||
|
||||
### Application Layer Optimization
|
||||
|
||||
```yaml
|
||||
# Enable Gzip compression
|
||||
server:
|
||||
gzip: true
|
||||
|
||||
# Adjust concurrent connections
|
||||
server:
|
||||
max_connections: 1000
|
||||
```
|
||||
|
||||
## Upgrade Guide
|
||||
|
||||
### Docker Upgrade
|
||||
|
||||
```bash
|
||||
# Pull latest image
|
||||
docker pull ghcr.io/perfect-panel/ppanel:latest
|
||||
|
||||
# Stop old container
|
||||
docker stop ppanel-backend
|
||||
|
||||
# Backup data
|
||||
docker exec ppanel-mysql mysqldump -u ppanel -p ppanel > backup.sql
|
||||
|
||||
# Remove old container
|
||||
docker rm ppanel-backend
|
||||
|
||||
# Run new container
|
||||
docker run -d \
|
||||
--name ppanel-backend \
|
||||
-p 8080:8080 \
|
||||
-v $(pwd)/config.yaml:/app/config.yaml \
|
||||
--link ppanel-mysql:mysql \
|
||||
--link ppanel-redis:redis \
|
||||
ghcr.io/perfect-panel/ppanel:latest
|
||||
|
||||
# Execute database migration
|
||||
docker exec ppanel-backend ./ppanel migrate
|
||||
```
|
||||
|
||||
### Binary Upgrade
|
||||
|
||||
```bash
|
||||
# Stop service
|
||||
sudo systemctl stop ppanel
|
||||
|
||||
# Backup old version
|
||||
sudo cp /opt/ppanel/ppanel /opt/ppanel/ppanel.backup
|
||||
|
||||
# Download new version
|
||||
wget https://github.com/perfect-panel/ppanel/releases/latest/download/ppanel-linux-amd64.tar.gz
|
||||
tar -xzf ppanel-linux-amd64.tar.gz
|
||||
|
||||
# Replace file
|
||||
sudo mv ppanel /opt/ppanel/
|
||||
sudo chown ppanel:ppanel /opt/ppanel/ppanel
|
||||
|
||||
# Execute database migration
|
||||
cd /opt/ppanel
|
||||
sudo -u ppanel ./ppanel migrate
|
||||
|
||||
# Start service
|
||||
sudo systemctl start ppanel
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
- [Frontend Separation Deployment](./frontend.md) - Deploy frontend application
|
||||
- [Node Agent Installation](../node/installation.md) - Deploy node service
|
||||
- [API Documentation](/api/reference) - View complete API documentation
|
||||
@@ -0,0 +1,689 @@
|
||||
# Frontend Separation Deployment
|
||||
|
||||
This guide will help you independently deploy PPanel frontend applications and connect them to the deployed backend service.
|
||||
|
||||
## Overview
|
||||
|
||||
Frontend separation deployment allows you to deploy PPanel frontend applications on independent servers or CDN, communicating with backend services through APIs.
|
||||
|
||||
PPanel frontend includes two independent applications:
|
||||
- **User Web** (`ppanel-user-web`): User-facing interface
|
||||
- **Admin Web** (`ppanel-admin-web`): Administrator backend management interface
|
||||
|
||||
### Advantages
|
||||
|
||||
- 🚀 Leverage CDN to accelerate static resource access
|
||||
- 🌍 Support multi-region distribution
|
||||
- 📦 Independent frontend deployment without affecting backend services
|
||||
- 🔄 Facilitate rapid frontend iteration and updates
|
||||
- 🎨 Modern tech stack (React 19, TypeScript, TailwindCSS 4)
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Completed [Backend Deployment](./backend.md)
|
||||
- Backend API address (e.g., `https://api.your-domain.com`)
|
||||
- Frontend domains:
|
||||
- User Web: `https://user.your-domain.com`
|
||||
- Admin Web: `https://admin.your-domain.com`
|
||||
|
||||
## Tech Stack
|
||||
|
||||
- **Runtime**: Bun (recommended) / Node.js 20+
|
||||
- **Build Tool**: Vite 6
|
||||
- **Framework**: React 19 + TypeScript
|
||||
- **Router**: TanStack Router
|
||||
- **Styling**: TailwindCSS 4
|
||||
- **State Management**: Zustand
|
||||
- **i18n**: i18next
|
||||
- **Monorepo**: Turborepo
|
||||
|
||||
## Deployment Methods
|
||||
|
||||
### Method 1: Build from Source (Recommended)
|
||||
|
||||
#### 1. Environment Setup
|
||||
|
||||
Install Bun (recommended):
|
||||
|
||||
```bash
|
||||
# Linux/macOS
|
||||
curl -fsSL https://bun.sh/install | bash
|
||||
|
||||
# Windows (WSL2)
|
||||
curl -fsSL https://bun.sh/install | bash
|
||||
|
||||
# Verify installation
|
||||
bun --version
|
||||
```
|
||||
|
||||
Or use Node.js (requires 20+):
|
||||
|
||||
```bash
|
||||
# Check Node.js version
|
||||
node --version # Should be v20 or higher
|
||||
```
|
||||
|
||||
#### 2. Clone Repository
|
||||
|
||||
```bash
|
||||
git clone https://github.com/perfect-panel/frontend.git
|
||||
cd frontend
|
||||
```
|
||||
|
||||
#### 3. Install Dependencies
|
||||
|
||||
```bash
|
||||
# Using Bun (recommended, faster)
|
||||
bun install
|
||||
|
||||
# Or using npm
|
||||
npm install
|
||||
|
||||
# Or using pnpm
|
||||
pnpm install
|
||||
```
|
||||
|
||||
#### 4. Configure Environment Variables
|
||||
|
||||
Create environment configuration files in application directories.
|
||||
|
||||
**Admin Web Config** (`apps/admin/.env.production`):
|
||||
|
||||
```bash
|
||||
# Backend API address (required)
|
||||
VITE_API_BASE_URL=https://api.your-domain.com
|
||||
|
||||
# CDN address (optional, for accelerating static resources)
|
||||
VITE_CDN_URL=https://cdn.jsdmirror.com
|
||||
|
||||
# Enable tutorial documentation (optional)
|
||||
VITE_TUTORIAL_DOCUMENT=true
|
||||
|
||||
# Development default credentials (leave empty in production)
|
||||
VITE_USER_EMAIL=
|
||||
VITE_USER_PASSWORD=
|
||||
```
|
||||
|
||||
**User Web Config** (`apps/user/.env.production`):
|
||||
|
||||
```bash
|
||||
# Backend API address (required)
|
||||
VITE_API_BASE_URL=https://api.your-domain.com
|
||||
|
||||
# CDN address (optional)
|
||||
VITE_CDN_URL=https://cdn.jsdmirror.com
|
||||
|
||||
# Enable tutorial documentation (optional)
|
||||
VITE_TUTORIAL_DOCUMENT=true
|
||||
|
||||
# Development default credentials (leave empty in production)
|
||||
VITE_USER_EMAIL=
|
||||
VITE_USER_PASSWORD=
|
||||
```
|
||||
|
||||
#### 5. Build Applications
|
||||
|
||||
Build all applications:
|
||||
|
||||
```bash
|
||||
# Using Bun
|
||||
bun run build
|
||||
|
||||
# Or using npm
|
||||
npm run build
|
||||
```
|
||||
|
||||
Build specific application:
|
||||
|
||||
```bash
|
||||
# Navigate to application directory
|
||||
cd apps/admin # or apps/user
|
||||
|
||||
# Build
|
||||
bun run build # or npm run build
|
||||
```
|
||||
|
||||
After build completes, static files will be output to:
|
||||
- Admin Web: `apps/admin/dist/`
|
||||
- User Web: `apps/user/dist/`
|
||||
|
||||
#### 6. Preview Build
|
||||
|
||||
```bash
|
||||
# In application directory
|
||||
bun run serve # or npm run serve
|
||||
|
||||
# Default access address:
|
||||
# Admin Web: http://localhost:4173
|
||||
# User Web: http://localhost:4173
|
||||
```
|
||||
|
||||
### Method 2: Deploy with Vercel (One-Click)
|
||||
|
||||
#### Admin Web Deployment
|
||||
|
||||
Click the button below to deploy to Vercel with one click:
|
||||
|
||||
[](https://vercel.com/new/clone?demo-description=PPanel%20is%20a%20pure%2C%20professional%2C%20and%20perfect%20open-source%20proxy%20panel%20tool&demo-image=https%3A%2F%2Furlscan.io%2Fliveshot%2F%3Fwidth%3D1920%26height%3D1080%26url%3Dhttps%3A%2F%2Fadmin.ppanel.dev&demo-title=PPanel%20Admin%20Web&repository-url=https%3A%2F%2Fgithub.com%2Fperfect-panel%2Ffrontend&root-directory=apps%2Fadmin)
|
||||
|
||||
#### User Web Deployment
|
||||
|
||||
[](https://vercel.com/new/clone?demo-description=PPanel%20is%20a%20pure%2C%20professional%2C%20and%20perfect%20open-source%20proxy%20panel%20tool&demo-image=https%3A%2F%2Furlscan.io%2Fliveshot%2F%3Fwidth%3D1920%26height%3D1080%26url%3Dhttps%3A%2F%2Fuser.ppanel.dev&demo-title=PPanel%20User%20Web&repository-url=https%3A%2F%2Fgithub.com%2Fperfect-panel%2Ffrontend&root-directory=apps%2Fuser)
|
||||
|
||||
After deployment, configure environment variables in Vercel console:
|
||||
- `VITE_API_BASE_URL`: Your backend API address
|
||||
- `VITE_CDN_URL`: CDN address (optional)
|
||||
|
||||
### Method 3: Deploy with Netlify
|
||||
|
||||
#### 1. Install Netlify CLI
|
||||
|
||||
```bash
|
||||
npm install -g netlify-cli
|
||||
```
|
||||
|
||||
#### 2. Login to Netlify
|
||||
|
||||
```bash
|
||||
netlify login
|
||||
```
|
||||
|
||||
#### 3. Deploy Application
|
||||
|
||||
```bash
|
||||
# Admin Web
|
||||
cd apps/admin
|
||||
bun run build
|
||||
netlify deploy --prod --dir=dist
|
||||
|
||||
# User Web
|
||||
cd apps/user
|
||||
bun run build
|
||||
netlify deploy --prod --dir=dist
|
||||
```
|
||||
|
||||
#### 4. Configure Environment Variables
|
||||
|
||||
Add in Netlify console under Site settings → Build & deploy → Environment:
|
||||
- `VITE_API_BASE_URL`
|
||||
- `VITE_CDN_URL`
|
||||
|
||||
### Method 4: Deploy with Cloudflare Pages
|
||||
|
||||
#### 1. Connect GitHub Repository
|
||||
|
||||
Login to Cloudflare Dashboard → Workers & Pages → Create application → Pages → Connect to Git
|
||||
|
||||
#### 2. Configure Build Settings
|
||||
|
||||
**Admin Web**:
|
||||
- **Framework preset**: None
|
||||
- **Build command**: `cd .. && bun install && cd apps/admin && bun run build`
|
||||
- **Build output directory**: `apps/admin/dist`
|
||||
- **Root directory**: `apps/admin`
|
||||
|
||||
**User Web**:
|
||||
- **Framework preset**: None
|
||||
- **Build command**: `cd .. && bun install && cd apps/user && bun run build`
|
||||
- **Build output directory**: `apps/user/dist`
|
||||
- **Root directory**: `apps/user`
|
||||
|
||||
#### 3. Configure Environment Variables
|
||||
|
||||
Add in Settings → Environment variables:
|
||||
- `VITE_API_BASE_URL`
|
||||
- `VITE_CDN_URL`
|
||||
|
||||
## Self-Hosted Server Deployment
|
||||
|
||||
### Using Nginx
|
||||
|
||||
#### 1. Install Nginx
|
||||
|
||||
```bash
|
||||
# Ubuntu/Debian
|
||||
sudo apt update
|
||||
sudo apt install nginx -y
|
||||
|
||||
# CentOS/RHEL
|
||||
sudo yum install nginx -y
|
||||
```
|
||||
|
||||
#### 2. Upload Build Files
|
||||
|
||||
```bash
|
||||
# Create directories
|
||||
sudo mkdir -p /var/www/ppanel/{admin,user}
|
||||
|
||||
# Upload build files
|
||||
sudo cp -r apps/admin/dist/* /var/www/ppanel/admin/
|
||||
sudo cp -r apps/user/dist/* /var/www/ppanel/user/
|
||||
|
||||
# Set permissions
|
||||
sudo chown -R www-data:www-data /var/www/ppanel
|
||||
```
|
||||
|
||||
#### 3. Configure Nginx
|
||||
|
||||
**Admin Web Config** (`/etc/nginx/sites-available/ppanel-admin`):
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 80;
|
||||
server_name admin.your-domain.com;
|
||||
|
||||
root /var/www/ppanel/admin;
|
||||
index index.html;
|
||||
|
||||
# Gzip compression
|
||||
gzip on;
|
||||
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
|
||||
gzip_vary on;
|
||||
gzip_min_length 1024;
|
||||
|
||||
# Static resource caching
|
||||
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
|
||||
expires 1y;
|
||||
add_header Cache-Control "public, immutable";
|
||||
}
|
||||
|
||||
# SPA routing support
|
||||
location / {
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
||||
# Security headers
|
||||
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||
add_header X-Content-Type-Options "nosniff" always;
|
||||
add_header X-XSS-Protection "1; mode=block" always;
|
||||
add_header Referrer-Policy "no-referrer-when-downgrade" always;
|
||||
}
|
||||
```
|
||||
|
||||
**User Web Config** (`/etc/nginx/sites-available/ppanel-user`):
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 80;
|
||||
server_name user.your-domain.com;
|
||||
|
||||
root /var/www/ppanel/user;
|
||||
index index.html;
|
||||
|
||||
# Other config same as admin web
|
||||
gzip on;
|
||||
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
|
||||
|
||||
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
|
||||
expires 1y;
|
||||
add_header Cache-Control "public, immutable";
|
||||
}
|
||||
|
||||
location / {
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
||||
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||
add_header X-Content-Type-Options "nosniff" always;
|
||||
add_header X-XSS-Protection "1; mode=block" always;
|
||||
}
|
||||
```
|
||||
|
||||
#### 4. Enable Sites
|
||||
|
||||
```bash
|
||||
# Enable sites
|
||||
sudo ln -s /etc/nginx/sites-available/ppanel-admin /etc/nginx/sites-enabled/
|
||||
sudo ln -s /etc/nginx/sites-available/ppanel-user /etc/nginx/sites-enabled/
|
||||
|
||||
# Test configuration
|
||||
sudo nginx -t
|
||||
|
||||
# Reload Nginx
|
||||
sudo systemctl reload nginx
|
||||
```
|
||||
|
||||
#### 5. Configure HTTPS (Recommended)
|
||||
|
||||
Use Certbot to automatically configure SSL certificates:
|
||||
|
||||
```bash
|
||||
# Install Certbot
|
||||
sudo apt install certbot python3-certbot-nginx -y
|
||||
|
||||
# Obtain certificates
|
||||
sudo certbot --nginx -d admin.your-domain.com
|
||||
sudo certbot --nginx -d user.your-domain.com
|
||||
|
||||
# Test auto-renewal
|
||||
sudo certbot renew --dry-run
|
||||
```
|
||||
|
||||
### Using Caddy
|
||||
|
||||
Caddy automatically handles HTTPS with simpler configuration.
|
||||
|
||||
#### 1. Install Caddy
|
||||
|
||||
```bash
|
||||
# Ubuntu/Debian
|
||||
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https
|
||||
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
|
||||
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
|
||||
sudo apt update
|
||||
sudo apt install caddy
|
||||
```
|
||||
|
||||
#### 2. Configure Caddyfile
|
||||
|
||||
Create `/etc/caddy/Caddyfile`:
|
||||
|
||||
```caddy
|
||||
admin.your-domain.com {
|
||||
root * /var/www/ppanel/admin
|
||||
encode gzip
|
||||
file_server
|
||||
|
||||
try_files {path} /index.html
|
||||
|
||||
@static {
|
||||
path *.js *.css *.png *.jpg *.jpeg *.gif *.ico *.svg *.woff *.woff2 *.ttf *.eot
|
||||
}
|
||||
header @static Cache-Control "public, max-age=31536000, immutable"
|
||||
|
||||
header {
|
||||
X-Frame-Options "SAMEORIGIN"
|
||||
X-Content-Type-Options "nosniff"
|
||||
X-XSS-Protection "1; mode=block"
|
||||
}
|
||||
}
|
||||
|
||||
user.your-domain.com {
|
||||
root * /var/www/ppanel/user
|
||||
encode gzip
|
||||
file_server
|
||||
|
||||
try_files {path} /index.html
|
||||
|
||||
@static {
|
||||
path *.js *.css *.png *.jpg *.jpeg *.gif *.ico *.svg *.woff *.woff2 *.ttf *.eot
|
||||
}
|
||||
header @static Cache-Control "public, max-age=31536000, immutable"
|
||||
|
||||
header {
|
||||
X-Frame-Options "SAMEORIGIN"
|
||||
X-Content-Type-Options "nosniff"
|
||||
X-XSS-Protection "1; mode=block"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 3. Start Caddy
|
||||
|
||||
```bash
|
||||
sudo systemctl restart caddy
|
||||
sudo systemctl enable caddy
|
||||
```
|
||||
|
||||
## CDN Configuration
|
||||
|
||||
### Cloudflare Configuration
|
||||
|
||||
1. Add domain to Cloudflare
|
||||
2. Configure DNS records pointing to origin server
|
||||
3. Enable optimization options:
|
||||
- **Auto Minify**: Enable JavaScript, CSS, HTML minification
|
||||
- **Brotli**: Enable Brotli compression
|
||||
- **Rocket Loader**: Enable JS async loading (optional)
|
||||
- **Caching Level**: Set to Standard
|
||||
|
||||
4. Configure page rules:
|
||||
```
|
||||
*your-domain.com/*
|
||||
- Cache Level: Cache Everything
|
||||
- Edge Cache TTL: 1 month
|
||||
- Browser Cache TTL: Respect Existing Headers
|
||||
```
|
||||
|
||||
### Alibaba Cloud CDN
|
||||
|
||||
1. Create CDN acceleration domain
|
||||
2. Configure origin server: Point to frontend server
|
||||
3. Configure caching rules:
|
||||
- Static files (js, css, images): Cache 1 year
|
||||
- HTML files: Cache 5 minutes or no cache
|
||||
4. Enable HTTPS and HTTP/2
|
||||
|
||||
## Environment Variables
|
||||
|
||||
| Variable | Description | Required | Default | Example |
|
||||
|----------|-------------|----------|---------|---------|
|
||||
| `VITE_API_BASE_URL` | Backend API address | ✅ | - | `https://api.your-domain.com` |
|
||||
| `VITE_CDN_URL` | CDN address | ❌ | `https://cdn.jsdmirror.com` | `https://cdn.your-domain.com` |
|
||||
| `VITE_TUTORIAL_DOCUMENT` | Enable tutorial docs | ❌ | `true` | `true` / `false` |
|
||||
| `VITE_USER_EMAIL` | Default login email (dev only) | ❌ | - | - |
|
||||
| `VITE_USER_PASSWORD` | Default login password (dev only) | ❌ | - | - |
|
||||
|
||||
## Verify Deployment
|
||||
|
||||
### Check Frontend Service
|
||||
|
||||
```bash
|
||||
# Access frontend addresses
|
||||
curl -I https://admin.your-domain.com
|
||||
curl -I https://user.your-domain.com
|
||||
|
||||
# Expected output
|
||||
# HTTP/2 200
|
||||
# content-type: text/html
|
||||
```
|
||||
|
||||
### Check API Connection
|
||||
|
||||
Open frontend address in browser, open developer tools:
|
||||
|
||||
1. Check Network tab
|
||||
2. Verify API requests are successful
|
||||
3. Confirm request addresses are correct (`https://api.your-domain.com`)
|
||||
4. Check response data is normal
|
||||
|
||||
### Check Build Version
|
||||
|
||||
Access `/version.lock` file to view currently deployed version:
|
||||
|
||||
```bash
|
||||
curl https://admin.your-domain.com/version.lock
|
||||
# Example output: 1.2.0
|
||||
```
|
||||
|
||||
## Performance Optimization
|
||||
|
||||
### 1. Enable HTTP/2
|
||||
|
||||
In Nginx:
|
||||
|
||||
```nginx
|
||||
listen 443 ssl http2;
|
||||
```
|
||||
|
||||
### 2. Enable Brotli Compression
|
||||
|
||||
```bash
|
||||
# Install Nginx Brotli module
|
||||
sudo apt install libnginx-mod-http-brotli-filter libnginx-mod-http-brotli-static -y
|
||||
```
|
||||
|
||||
In Nginx configuration:
|
||||
|
||||
```nginx
|
||||
brotli on;
|
||||
brotli_types text/plain text/css application/json application/javascript text/xml application/xml;
|
||||
brotli_comp_level 6;
|
||||
```
|
||||
|
||||
### 3. Preload Critical Resources
|
||||
|
||||
Vite automatically handles this during build, adding `<link rel="modulepreload">` in `index.html`.
|
||||
|
||||
### 4. Enable Service Worker
|
||||
|
||||
Frontend has built-in PWA support, Service Worker caching is automatically enabled after build.
|
||||
|
||||
### 5. Use CDN Acceleration
|
||||
|
||||
Configure `VITE_CDN_URL` environment variable to load static resources from CDN.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### API Request Failed
|
||||
|
||||
**Issue**: Frontend cannot connect to backend API
|
||||
|
||||
**Solution**:
|
||||
1. Check if `VITE_API_BASE_URL` is correctly configured
|
||||
2. Check if backend CORS configuration allows frontend domain
|
||||
3. Open browser console for specific error messages
|
||||
4. Use `curl` to test if backend API is accessible
|
||||
|
||||
```bash
|
||||
curl https://api.your-domain.com/api/health
|
||||
```
|
||||
|
||||
### Page Route 404
|
||||
|
||||
**Issue**: Refreshing page or directly accessing sub-route returns 404
|
||||
|
||||
**Solution**: Ensure web server has SPA fallback configured
|
||||
|
||||
```nginx
|
||||
# Nginx
|
||||
try_files $uri $uri/ /index.html;
|
||||
|
||||
# Apache (.htaccess)
|
||||
RewriteEngine On
|
||||
RewriteBase /
|
||||
RewriteRule ^index\.html$ - [L]
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteRule . /index.html [L]
|
||||
```
|
||||
|
||||
### Static Resource Loading Failed
|
||||
|
||||
**Issue**: JS/CSS files 404 or cannot load
|
||||
|
||||
**Solution**:
|
||||
1. Check file permissions
|
||||
2. Check if Nginx `root` path is correct
|
||||
3. Clear browser cache
|
||||
4. Check CDN configuration
|
||||
|
||||
### Build Failed
|
||||
|
||||
**Issue**: `bun run build` or `npm run build` fails
|
||||
|
||||
**Solution**:
|
||||
1. Ensure Node.js version >= 20
|
||||
2. Delete `node_modules` and lock file, reinstall
|
||||
```bash
|
||||
rm -rf node_modules bun.lockb
|
||||
bun install
|
||||
```
|
||||
3. Check for syntax errors or type errors
|
||||
```bash
|
||||
bun run check
|
||||
```
|
||||
|
||||
## Update Deployment
|
||||
|
||||
### Update from Source
|
||||
|
||||
```bash
|
||||
# Pull latest code
|
||||
git pull origin main
|
||||
|
||||
# Reinstall dependencies
|
||||
bun install
|
||||
|
||||
# Rebuild
|
||||
bun run build
|
||||
|
||||
# Update files
|
||||
sudo rm -rf /var/www/ppanel/admin
|
||||
sudo rm -rf /var/www/ppanel/user
|
||||
sudo cp -r apps/admin/dist /var/www/ppanel/admin
|
||||
sudo cp -r apps/user/dist /var/www/ppanel/user
|
||||
|
||||
# Clear CDN cache (if using CDN)
|
||||
```
|
||||
|
||||
### Vercel Update
|
||||
|
||||
Vercel automatically monitors GitHub repository changes and deploys automatically. Can also trigger manually:
|
||||
|
||||
```bash
|
||||
vercel --prod
|
||||
```
|
||||
|
||||
### Netlify Update
|
||||
|
||||
```bash
|
||||
cd apps/admin # or apps/user
|
||||
bun run build
|
||||
netlify deploy --prod
|
||||
```
|
||||
|
||||
## Security Recommendations
|
||||
|
||||
1. **Enable HTTPS**: Must use SSL/TLS certificates
|
||||
2. **Configure CSP**: Content Security Policy
|
||||
```nginx
|
||||
add_header Content-Security-Policy "default-src 'self'; connect-src 'self' https://api.your-domain.com; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' 'unsafe-eval';";
|
||||
```
|
||||
3. **Set Security Headers**: Already included in Nginx configuration
|
||||
4. **Disable Directory Browsing**: `Options -Indexes` (Apache) or `autoindex off;` (Nginx)
|
||||
5. **Limit File Upload Size**:
|
||||
```nginx
|
||||
client_max_body_size 10M;
|
||||
```
|
||||
|
||||
## Monitoring and Analytics
|
||||
|
||||
### Add Web Analytics
|
||||
|
||||
Supports Google Analytics, Umami, Plausible, etc.
|
||||
|
||||
Configuration: Add tracking code in `index.html` or configure via environment variables.
|
||||
|
||||
### Error Tracking
|
||||
|
||||
Frontend supports integrating Sentry for error tracking (needs code configuration).
|
||||
|
||||
## Development and Production
|
||||
|
||||
### Local Development
|
||||
|
||||
```bash
|
||||
# Use development server
|
||||
cd apps/admin # or apps/user
|
||||
bun run dev
|
||||
|
||||
# Admin Web runs on http://localhost:3001 by default
|
||||
# User Web runs on http://localhost:3000 by default
|
||||
```
|
||||
|
||||
Development environment uses Vite's proxy feature to proxy API requests to backend.
|
||||
|
||||
### Preview Production Build
|
||||
|
||||
```bash
|
||||
# Preview after build
|
||||
bun run build
|
||||
bun run serve
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
- [Backend Separation Deployment](./backend.md) - If backend not yet deployed
|
||||
- [Node Agent Installation](../node/installation.md) - Deploy node service
|
||||
- [Feature Documentation](/admin/dashboard) - Learn feature usage
|
||||
Reference in New Issue
Block a user