2407 lines
92 KiB
HTML
2407 lines
92 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="fr">
|
|
<head>
|
|
<link rel="preconnect" href="https://d3js.org" crossorigin>
|
|
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
|
|
<link rel="alternate icon" href="/favicon.ico">
|
|
<title>VPS Odoo Hosting 2026 | Odoo Expertos · FR</title>
|
|
|
|
<meta name="description" content="Guia completa de VPS pour Odoo en 2026. Compourmos Hetzner, DigitalOcean, Vultr y Contabo. Incluye instalacion paso a paso, configuracio - VPS Odoo Hosting 2026 | FR">
|
|
<meta name="keywords" content="vps odoo, servidor vps odoo, hetzner odoo, digitalocean odoo, vultr odoo, contabo odoo, instalar odoo vps, configurar servidor odoo, optimizar odoo vps">
|
|
<meta name="author" content="Dr. Equipo Odoo Expertos">
|
|
<meta name="robots" content="index, follow">
|
|
<meta name="language" content="fr">
|
|
|
|
<link rel="canonical" href="https://www.odoo-expertos.com/fr/odoo-hosting/vps-odoo-hosting-2026/">
|
|
|
|
<!-- Hreflang -->
|
|
<link rel="alternate" hreflang="fr" href="https://www.odoo-expertos.com/fr/odoo-hosting/vps-odoo-hosting-2026/" />
|
|
<link rel="alternate" hreflang="en" href="https://www.odoo-expertos.com/en/odoo-hosting/vps-odoo-hosting-2026/" />
|
|
<link rel="alternate" hreflang="de" href="https://www.odoo-expertos.com/de/odoo-hosting/vps-odoo-hosting-2026/" />
|
|
<link rel="alternate" hreflang="fr" href="https://www.odoo-expertos.com/fr/odoo-hosting/vps-odoo-hosting-2026/" />
|
|
<link rel="alternate" hreflang="x-default" href="https://www.odoo-expertos.com/odoo-hosting/vps-odoo-hosting-2026/" />
|
|
|
|
<!-- Open Graph -->
|
|
<meta property="og:title" content="VPS Odoo Hébergement Guia 2026: Compourison de Fournisseurs y Configuracion">
|
|
<meta property="og:description" content="Guia definitiva de VPS pour Odoo. Compourmos Hetzner, DigitalOcean, Vultr y Contabo con precios, rendimiento y tutoriales de instalacion.">
|
|
<meta property="og:type" content="article">
|
|
<meta property="og:url" content="https://www.odoo-expertos.com/fr/odoo-hosting/vps-odoo-hosting-2026/">
|
|
<meta property="og:image" content="https://www.odoo-expertos.com/images/vps-odoo-hosting-2026.jpg">
|
|
<meta property="og:site_name" content="Odoo Expertos">
|
|
<meta property="og:locale" content="fr_FR">
|
|
|
|
<!-- Twitter Card -->
|
|
<meta name="twitter:card" content="summary_large_image">
|
|
<meta name="twitter:title" content="VPS Odoo Hébergement Guia 2026: Compourison Définitif">
|
|
<meta name="twitter:description" content="Guia completa de VPS pour Odoo. Compourmos los mejores proveedores con instalacion y configuracion paso a paso.">
|
|
|
|
<!-- Schema.org Article -->
|
|
<script type="application/ld+json">
|
|
{
|
|
"@context": "https://schema.org",
|
|
"@type": "TechArticle",
|
|
"headline": "VPS Odoo Hébergement Guia 2026: Compourison y Configuracion Completa",
|
|
"description": "Guia completa de VPS pour Odoo en 2026. Compourmos Hetzner, DigitalOcean, Vultr y Contabo con instalacion, configuracion, optimizacion y seguridad.",
|
|
"author": {
|
|
"@type": "Person",
|
|
"name": "Dr. Equipo Odoo Expertos",
|
|
"url": "https://www.odoo-expertos.com/autor/maria-elena-rodriguez/",
|
|
"jobTitle": "Consultante Senior en Systèmes ERP"
|
|
},
|
|
"publisher": {
|
|
"@type": "Organization",
|
|
"name": "Odoo Expertos",
|
|
"logo": {
|
|
"@type": "ImageObject",
|
|
"url": "https://www.odoo-expertos.com/logo.png"
|
|
}
|
|
},
|
|
"datePublished": "2026-01-25",
|
|
"dateModified": "2026-01-25",
|
|
"mainEntityOfPage": {
|
|
"@type": "WebPage",
|
|
"@id": "https://www.odoo-expertos.com/fr/odoo-hosting/vps-odoo-hosting-2026/"
|
|
},
|
|
"proficiencyLevel": "Intermediate",
|
|
"dependencies": "Ubuntu 22.04 LTS, PostgreSQL 16, Python 3.12"
|
|
}
|
|
</script>
|
|
|
|
<!-- HowTo Schema -->
|
|
<script type="application/ld+json">
|
|
{
|
|
"@context": "https://schema.org",
|
|
"@type": "HowTo",
|
|
"name": "Como Instalar Odoo en un VPS",
|
|
"description": "Guia paso a paso pour instalar y configurar Odoo 18 en un servidor VPS",
|
|
"totalTime": "PT45M",
|
|
"estimatedCost": {
|
|
"@type": "MonetaryAmount",
|
|
"currency": "EUR",
|
|
"value": "6-50"
|
|
},
|
|
"supply": [
|
|
{"@type": "HowToSupply", "name": "Servidor VPS con Ubuntu 22.04"},
|
|
{"@type": "HowToSupply", "name": "Dominio con DNS configurado"},
|
|
{"@type": "HowToSupply", "name": "Acceso SSH root"}
|
|
],
|
|
"tool": [
|
|
{"@type": "HowToTool", "name": "Terminal SSH"},
|
|
{"@type": "HowToTool", "name": "Editor de texto"}
|
|
],
|
|
"step": [
|
|
{
|
|
"@type": "HowToStep",
|
|
"position": 1,
|
|
"name": "Prepourr el servidor",
|
|
"text": "Actualizar el sistema y crear usuario odoo"
|
|
},
|
|
{
|
|
"@type": "HowToStep",
|
|
"position": 2,
|
|
"name": "Instalar dependencias",
|
|
"text": "Instalar PostgreSQL, Python y paquetes necesarios"
|
|
},
|
|
{
|
|
"@type": "HowToStep",
|
|
"position": 3,
|
|
"name": "Instalar Odoo",
|
|
"text": "Clonar repositorio y configurar Odoo"
|
|
},
|
|
{
|
|
"@type": "HowToStep",
|
|
"position": 4,
|
|
"name": "Configurar Nginx",
|
|
"text": "Configurar proxy inverso con SSL"
|
|
},
|
|
{
|
|
"@type": "HowToStep",
|
|
"position": 5,
|
|
"name": "Asegurar el servidor",
|
|
"text": "Configurar firewall y hardening de seguridad"
|
|
}
|
|
]
|
|
}
|
|
</script>
|
|
|
|
<!-- FAQ Schema -->
|
|
<script type="application/ld+json">
|
|
{
|
|
"@context": "https://schema.org",
|
|
"@type": "FAQPage",
|
|
"mainEntity": [
|
|
{
|
|
"@type": "Question",
|
|
"name": "Cual es el mejor VPS pour Odoo en 2026?",
|
|
"acceptedAnswer": {
|
|
"@type": "Answer",
|
|
"text": "Pour la mayoria de casos, Hetzner ofrece la mejor relacion calidad-precio con servidores en Europe. DigitalOcean es ideal si priorizas documentacion y facilidad de uso. Vultr destaca por su red global y Contabo por precios muy economicos."
|
|
}
|
|
},
|
|
{
|
|
"@type": "Question",
|
|
"name": "Cuanta RAM necesita Odoo en un VPS?",
|
|
"acceptedAnswer": {
|
|
"@type": "Answer",
|
|
"text": "Pour Odoo Community con 1-10 usuarios: 4GB RAM minimo. Pour 10-25 usuarios: 8GB RAM. Pour 25-50 usuarios: 16GB RAM. Odoo Enterprise requiere aproximadamente el doble de recursos."
|
|
}
|
|
},
|
|
{
|
|
"@type": "Question",
|
|
"name": "Es dificil instalar Odoo en un VPS?",
|
|
"acceptedAnswer": {
|
|
"@type": "Answer",
|
|
"text": "Requiere conocimientos basicos de Linux y linea de comandos. Con esta guia, la instalacion toma aproximadamente 45 minutos. Si no tienes experiencia tecnica, considera usar hosting gestionado."
|
|
}
|
|
},
|
|
{
|
|
"@type": "Question",
|
|
"name": "Cuanto cuesta un VPS pour Odoo mensualmente?",
|
|
"acceptedAnswer": {
|
|
"@type": "Answer",
|
|
"text": "Los precios varian desde 6 euros/mes (Contabo, recursos basicos) hasta 50+ euros/mes pour servidores de alto rendimiento. El promedio pour una PYME es 15-30 euros/mes."
|
|
}
|
|
},
|
|
{
|
|
"@type": "Question",
|
|
"name": "Puedo migrar de Odoo.sh a un VPS propio?",
|
|
"acceptedAnswer": {
|
|
"@type": "Answer",
|
|
"text": "Si, es posible migrar exportando la base de datos PostgreSQL y el filestore. Sin embargo, perderas actualizaciones automaticas y soporte oficial. La migracion requiere conocimientos tecnicos avanzados."
|
|
}
|
|
},
|
|
{
|
|
"@type": "Question",
|
|
"name": "Como hacer backup de Odoo en un VPS?",
|
|
"acceptedAnswer": {
|
|
"@type": "Answer",
|
|
"text": "Debes hacer backup de: 1) Base de datos PostgreSQL con pg_dump, 2) Directorio filestore con los archivos adjuntos, 3) Archivo de configuracion odoo.conf. Recomendamos backups diarios automatizados con retencion de 30 dias."
|
|
}
|
|
}
|
|
]
|
|
}
|
|
</script>
|
|
|
|
<!-- Product Comparison Schema -->
|
|
<script type="application/ld+json">
|
|
{
|
|
"@context": "https://schema.org",
|
|
"@type": "ItemList",
|
|
"name": "Mejores Proveedores VPS pour Odoo 2026",
|
|
"itemListElement": [
|
|
{
|
|
"@type": "ListItem",
|
|
"position": 1,
|
|
"item": {
|
|
"@type": "Product",
|
|
"name": "Hetzner Cloud",
|
|
"description": "VPS de alto rendimiento con excelente relacion calidad-precio en Europe",
|
|
"offers": {
|
|
"@type": "Offer",
|
|
"price": "4.51",
|
|
"priceCurrency": "EUR"
|
|
},
|
|
"aggregateRating": {
|
|
"@type": "AggregateRating",
|
|
"ratingValue": "4.8",
|
|
"reviewCount": "2847"
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"@type": "ListItem",
|
|
"position": 2,
|
|
"item": {
|
|
"@type": "Product",
|
|
"name": "DigitalOcean Droplets",
|
|
"description": "VPS con excelente documentacion y comunidad activa",
|
|
"offers": {
|
|
"@type": "Offer",
|
|
"price": "6",
|
|
"priceCurrency": "USD"
|
|
},
|
|
"aggregateRating": {
|
|
"@type": "AggregateRating",
|
|
"ratingValue": "4.6",
|
|
"reviewCount": "5234"
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"@type": "ListItem",
|
|
"position": 3,
|
|
"item": {
|
|
"@type": "Product",
|
|
"name": "Vultr Cloud Compute",
|
|
"description": "VPS con red global de 32 ubicaciones",
|
|
"offers": {
|
|
"@type": "Offer",
|
|
"price": "6",
|
|
"priceCurrency": "USD"
|
|
},
|
|
"aggregateRating": {
|
|
"@type": "AggregateRating",
|
|
"ratingValue": "4.5",
|
|
"reviewCount": "3156"
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"@type": "ListItem",
|
|
"position": 4,
|
|
"item": {
|
|
"@type": "Product",
|
|
"name": "Contabo VPS",
|
|
"description": "VPS economico con recursos generosos",
|
|
"offers": {
|
|
"@type": "Offer",
|
|
"price": "5.99",
|
|
"priceCurrency": "EUR"
|
|
},
|
|
"aggregateRating": {
|
|
"@type": "AggregateRating",
|
|
"ratingValue": "4.1",
|
|
"reviewCount": "1823"
|
|
}
|
|
}
|
|
}
|
|
]
|
|
}
|
|
</script>
|
|
|
|
<!-- BreadcrumbList Schema -->
|
|
<script type="application/ld+json">
|
|
{
|
|
"@context": "https://schema.org",
|
|
"@type": "BreadcrumbList",
|
|
"itemListElement": [
|
|
{
|
|
"@type": "ListItem",
|
|
"position": 1,
|
|
"name": "Inicio",
|
|
"item": "https://www.odoo-expertos.com/"
|
|
},
|
|
{
|
|
"@type": "ListItem",
|
|
"position": 2,
|
|
"name": "Hosting Odoo",
|
|
"item": "https://www.odoo-expertos.com/fr/odoo-hosting/"
|
|
},
|
|
{
|
|
"@type": "ListItem",
|
|
"position": 3,
|
|
"name": "VPS Odoo Hosting 2026",
|
|
"item": "https://www.odoo-expertos.com/fr/odoo-hosting/vps-odoo-hosting-2026/"
|
|
}
|
|
]
|
|
}
|
|
</script>
|
|
|
|
<link rel="stylesheet" href="/css/main.min.css">
|
|
<style>
|
|
.pillar-hero {
|
|
background: linear-gradient(135deg, #1a1a1a 0%, #2a2a2a 50%, #1a1a1a 100%);
|
|
padding: 4rem 2rem;
|
|
text-align: center;
|
|
border-bottom: 3px solid #FF6B35;
|
|
position: relative;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.pillar-hero::before {
|
|
content: '';
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
background: radial-gradient(ellipse at center, rgba(255,107,53,0.15) 0%, transparent 70%);
|
|
pointer-events: none;
|
|
}
|
|
|
|
.pillar-hero h1 {
|
|
font-size: clamp(2rem, 5vw, 3.5rem);
|
|
color: #FF6B35;
|
|
margin-bottom: 1rem;
|
|
line-height: 1.2;
|
|
position: relative;
|
|
}
|
|
|
|
.pillar-subtitle {
|
|
font-size: 1.3rem;
|
|
color: #b0b0b0;
|
|
max-width: 800px;
|
|
margin: 0 auto 2rem;
|
|
}
|
|
|
|
.pillar-meta {
|
|
display: flex;
|
|
justify-content: center;
|
|
gap: 2rem;
|
|
flex-wrap: wrap;
|
|
font-size: 0.9rem;
|
|
color: #888;
|
|
}
|
|
|
|
.pillar-meta span {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
}
|
|
|
|
.quick-stats {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
|
|
gap: 1.5rem;
|
|
padding: 2rem;
|
|
background: #2a2a2a;
|
|
border-radius: 12px;
|
|
margin: 2rem 0;
|
|
}
|
|
|
|
.stat-card {
|
|
text-align: center;
|
|
padding: 1.5rem;
|
|
background: rgba(255,107,53,0.1);
|
|
border-radius: 8px;
|
|
border: 1px solid rgba(255,107,53,0.2);
|
|
transition: transform 0.3s ease, border-color 0.3s ease;
|
|
}
|
|
|
|
.stat-card:hover {
|
|
transform: translateY(-5px);
|
|
border-color: #FF6B35;
|
|
}
|
|
|
|
.stat-number {
|
|
font-size: 2.5rem;
|
|
font-weight: 700;
|
|
color: #FF6B35;
|
|
display: block;
|
|
}
|
|
|
|
.stat-label {
|
|
color: #b0b0b0;
|
|
font-size: 0.9rem;
|
|
margin-top: 0.5rem;
|
|
}
|
|
|
|
.toc {
|
|
background: #2a2a2a;
|
|
border: 2px solid #FF6B35;
|
|
border-radius: 12px;
|
|
padding: 2rem;
|
|
margin: 2rem 0;
|
|
}
|
|
|
|
.toc h2 {
|
|
color: #FF6B35;
|
|
margin-bottom: 1rem;
|
|
font-size: 1.5rem;
|
|
}
|
|
|
|
.toc-list {
|
|
list-style: none;
|
|
padding: 0;
|
|
columns: 2;
|
|
column-gap: 2rem;
|
|
}
|
|
|
|
.toc-list li {
|
|
margin-bottom: 0.75rem;
|
|
break-inside: avoid;
|
|
}
|
|
|
|
.toc-list a {
|
|
color: #e0e0e0;
|
|
text-decoration: none;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
transition: color 0.3s ease;
|
|
}
|
|
|
|
.toc-list a:hover {
|
|
color: #FF6B35;
|
|
}
|
|
|
|
.toc-list a::before {
|
|
content: '->';
|
|
color: #FF6B35;
|
|
}
|
|
|
|
.content-section {
|
|
margin: 3rem 0;
|
|
}
|
|
|
|
.content-section h2 {
|
|
color: #FF8A50;
|
|
margin-bottom: 1.5rem;
|
|
padding-bottom: 0.5rem;
|
|
border-bottom: 2px solid rgba(255,107,53,0.3);
|
|
}
|
|
|
|
.content-section h3 {
|
|
color: #FFB74D;
|
|
margin: 2rem 0 1rem;
|
|
}
|
|
|
|
.content-section h4 {
|
|
color: #FFC107;
|
|
margin: 1.5rem 0 0.75rem;
|
|
}
|
|
|
|
.chart-section {
|
|
margin: 3rem 0;
|
|
padding: 2rem;
|
|
background: #2a2a2a;
|
|
border-radius: 12px;
|
|
}
|
|
|
|
.chart-section h3 {
|
|
color: #FF8A50;
|
|
margin-bottom: 1rem;
|
|
}
|
|
|
|
.chart-container {
|
|
width: 100%;
|
|
min-height: 400px;
|
|
position: relative;
|
|
}
|
|
|
|
.comparison-table {
|
|
width: 100%;
|
|
border-collapse: collapse;
|
|
margin: 2rem 0;
|
|
background: #2a2a2a;
|
|
border-radius: 12px;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.comparison-table th,
|
|
.comparison-table td {
|
|
padding: 1rem;
|
|
text-align: left;
|
|
border-bottom: 1px solid #3a3a3a;
|
|
}
|
|
|
|
.comparison-table th {
|
|
background: rgba(255,107,53,0.2);
|
|
color: #FF6B35;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.comparison-table tr:hover {
|
|
background: rgba(255,107,53,0.05);
|
|
}
|
|
|
|
.comparison-table .check {
|
|
color: #4CAF50;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.comparison-table .cross {
|
|
color: #f44336;
|
|
}
|
|
|
|
.provider-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
|
|
gap: 1.5rem;
|
|
margin: 2rem 0;
|
|
}
|
|
|
|
.provider-card {
|
|
background: #2a2a2a;
|
|
border-radius: 12px;
|
|
padding: 1.5rem;
|
|
border: 1px solid rgba(255,107,53,0.2);
|
|
transition: transform 0.3s ease, border-color 0.3s ease;
|
|
}
|
|
|
|
.provider-card:hover {
|
|
transform: translateY(-5px);
|
|
border-color: #FF6B35;
|
|
}
|
|
|
|
.provider-card.featured {
|
|
border-color: #FF6B35;
|
|
background: linear-gradient(135deg, rgba(255,107,53,0.15) 0%, #2a2a2a 100%);
|
|
position: relative;
|
|
}
|
|
|
|
.provider-card .badge {
|
|
display: inline-block;
|
|
padding: 0.25rem 0.75rem;
|
|
background: #FF6B35;
|
|
color: #fff;
|
|
border-radius: 20px;
|
|
font-size: 0.8rem;
|
|
margin-bottom: 1rem;
|
|
}
|
|
|
|
.provider-card h4 {
|
|
color: #fff;
|
|
margin-bottom: 0.5rem;
|
|
font-size: 1.3rem;
|
|
}
|
|
|
|
.provider-card .price {
|
|
font-size: 2rem;
|
|
color: #FF6B35;
|
|
font-weight: 700;
|
|
}
|
|
|
|
.provider-card .price-period {
|
|
color: #888;
|
|
font-size: 0.9rem;
|
|
}
|
|
|
|
.provider-card ul {
|
|
list-style: none;
|
|
padding: 0;
|
|
margin: 1rem 0;
|
|
}
|
|
|
|
.provider-card li {
|
|
padding: 0.5rem 0;
|
|
border-bottom: 1px solid #3a3a3a;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
color: #b0b0b0;
|
|
}
|
|
|
|
.provider-card li::before {
|
|
content: 'OK';
|
|
color: #4CAF50;
|
|
font-weight: bold;
|
|
font-size: 0.8rem;
|
|
}
|
|
|
|
.provider-card .cta-btn {
|
|
display: block;
|
|
text-align: center;
|
|
padding: 0.75rem 1.5rem;
|
|
background: #FF6B35;
|
|
color: #fff;
|
|
border-radius: 8px;
|
|
text-decoration: none;
|
|
font-weight: 600;
|
|
transition: background 0.3s ease, transform 0.3s ease;
|
|
margin-top: 1rem;
|
|
}
|
|
|
|
.provider-card .cta-btn:hover {
|
|
background: #FF8A50;
|
|
transform: scale(1.02);
|
|
}
|
|
|
|
.code-block {
|
|
background: #1a1a1a;
|
|
border: 1px solid #3a3a3a;
|
|
border-radius: 8px;
|
|
padding: 1.5rem;
|
|
margin: 1.5rem 0;
|
|
overflow-x: auto;
|
|
font-family: 'Fira Code', 'Courier New', monospace;
|
|
font-size: 0.9rem;
|
|
line-height: 1.6;
|
|
}
|
|
|
|
.code-block code {
|
|
color: #e0e0e0;
|
|
}
|
|
|
|
.code-block .comment {
|
|
color: #6a9955;
|
|
}
|
|
|
|
.code-block .command {
|
|
color: #FF6B35;
|
|
}
|
|
|
|
.code-block .variable {
|
|
color: #9CDCFE;
|
|
}
|
|
|
|
.code-block .string {
|
|
color: #CE9178;
|
|
}
|
|
|
|
.step-list {
|
|
counter-reset: step-counter;
|
|
list-style: none;
|
|
padding: 0;
|
|
}
|
|
|
|
.step-list li {
|
|
counter-increment: step-counter;
|
|
position: relative;
|
|
padding-left: 3.5rem;
|
|
margin-bottom: 1.5rem;
|
|
padding-bottom: 1.5rem;
|
|
border-bottom: 1px solid #3a3a3a;
|
|
}
|
|
|
|
.step-list li::before {
|
|
content: counter(step-counter);
|
|
position: absolute;
|
|
left: 0;
|
|
top: 0;
|
|
width: 2.5rem;
|
|
height: 2.5rem;
|
|
background: #FF6B35;
|
|
border-radius: 50%;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-weight: 700;
|
|
color: #fff;
|
|
}
|
|
|
|
.step-list li h4 {
|
|
color: #FFB74D;
|
|
margin: 0 0 0.5rem 0;
|
|
}
|
|
|
|
.warning-box {
|
|
background: rgba(255, 193, 7, 0.1);
|
|
border-left: 4px solid #FFC107;
|
|
padding: 1.5rem;
|
|
margin: 2rem 0;
|
|
border-radius: 0 8px 8px 0;
|
|
}
|
|
|
|
.warning-box h4 {
|
|
color: #FFC107;
|
|
margin: 0 0 0.5rem 0;
|
|
}
|
|
|
|
.success-box {
|
|
background: rgba(76, 175, 80, 0.1);
|
|
border-left: 4px solid #4CAF50;
|
|
padding: 1.5rem;
|
|
margin: 2rem 0;
|
|
border-radius: 0 8px 8px 0;
|
|
}
|
|
|
|
.success-box h4 {
|
|
color: #4CAF50;
|
|
margin: 0 0 0.5rem 0;
|
|
}
|
|
|
|
.info-box {
|
|
background: rgba(33, 150, 243, 0.1);
|
|
border-left: 4px solid #2196F3;
|
|
padding: 1.5rem;
|
|
margin: 2rem 0;
|
|
border-radius: 0 8px 8px 0;
|
|
}
|
|
|
|
.info-box h4 {
|
|
color: #2196F3;
|
|
margin: 0 0 0.5rem 0;
|
|
}
|
|
|
|
.faq-section {
|
|
margin: 3rem 0;
|
|
}
|
|
|
|
.faq-item {
|
|
background: #2a2a2a;
|
|
border-radius: 8px;
|
|
margin-bottom: 1rem;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.faq-question {
|
|
padding: 1.25rem;
|
|
cursor: pointer;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
color: #fff;
|
|
font-weight: 500;
|
|
transition: background 0.3s ease;
|
|
}
|
|
|
|
.faq-question:hover {
|
|
background: rgba(255,107,53,0.1);
|
|
}
|
|
|
|
.faq-question::after {
|
|
content: '+';
|
|
font-size: 1.5rem;
|
|
color: #FF6B35;
|
|
transition: transform 0.3s ease;
|
|
}
|
|
|
|
.faq-item.open .faq-question::after {
|
|
transform: rotate(45deg);
|
|
}
|
|
|
|
.faq-answer {
|
|
padding: 0 1.25rem;
|
|
max-height: 0;
|
|
overflow: hidden;
|
|
transition: max-height 0.3s ease, padding 0.3s ease;
|
|
color: #b0b0b0;
|
|
}
|
|
|
|
.faq-item.open .faq-answer {
|
|
padding: 0 1.25rem 1.25rem;
|
|
max-height: 500px;
|
|
}
|
|
|
|
.cta-banner {
|
|
background: linear-gradient(135deg, rgba(255,107,53,0.2) 0%, rgba(255,138,80,0.1) 100%);
|
|
border: 2px solid rgba(255,107,53,0.5);
|
|
border-radius: 12px;
|
|
padding: 2.5rem;
|
|
text-align: center;
|
|
margin: 3rem 0;
|
|
}
|
|
|
|
.cta-banner h3 {
|
|
color: #FF6B35;
|
|
margin-bottom: 1rem;
|
|
font-size: 1.8rem;
|
|
}
|
|
|
|
.cta-banner p {
|
|
margin-bottom: 1.5rem;
|
|
color: #b0b0b0;
|
|
font-size: 1.1rem;
|
|
}
|
|
|
|
.cta-banner .cta-btn {
|
|
display: inline-block;
|
|
padding: 1rem 2.5rem;
|
|
background: #FF6B35;
|
|
color: #fff;
|
|
border-radius: 8px;
|
|
text-decoration: none;
|
|
font-weight: 600;
|
|
font-size: 1.1rem;
|
|
transition: background 0.3s ease, transform 0.3s ease;
|
|
}
|
|
|
|
.cta-banner .cta-btn:hover {
|
|
background: #FF8A50;
|
|
transform: scale(1.05);
|
|
}
|
|
|
|
.highlight-box {
|
|
background: linear-gradient(135deg, rgba(255,107,53,0.1) 0%, rgba(255,138,80,0.05) 100%);
|
|
border-left: 4px solid #FF6B35;
|
|
padding: 1.5rem;
|
|
margin: 2rem 0;
|
|
border-radius: 0 8px 8px 0;
|
|
}
|
|
|
|
.highlight-box h4 {
|
|
color: #FF6B35;
|
|
margin-bottom: 0.5rem;
|
|
}
|
|
|
|
.pros-cons {
|
|
display: grid;
|
|
grid-template-columns: 1fr 1fr;
|
|
gap: 1.5rem;
|
|
margin: 1.5rem 0;
|
|
}
|
|
|
|
.pros, .cons {
|
|
padding: 1.5rem;
|
|
border-radius: 8px;
|
|
}
|
|
|
|
.pros {
|
|
background: rgba(76, 175, 80, 0.1);
|
|
border: 1px solid rgba(76, 175, 80, 0.3);
|
|
}
|
|
|
|
.cons {
|
|
background: rgba(244, 67, 54, 0.1);
|
|
border: 1px solid rgba(244, 67, 54, 0.3);
|
|
}
|
|
|
|
.pros h4 {
|
|
color: #4CAF50;
|
|
margin-bottom: 1rem;
|
|
}
|
|
|
|
.cons h4 {
|
|
color: #f44336;
|
|
margin-bottom: 1rem;
|
|
}
|
|
|
|
.pros ul, .cons ul {
|
|
list-style: none;
|
|
padding: 0;
|
|
margin: 0;
|
|
}
|
|
|
|
.pros li::before {
|
|
content: '[OK] ';
|
|
color: #4CAF50;
|
|
}
|
|
|
|
.cons li::before {
|
|
content: '[X] ';
|
|
color: #f44336;
|
|
}
|
|
|
|
.d3-tooltip {
|
|
position: absolute;
|
|
background: rgba(0,0,0,0.95);
|
|
color: #fff;
|
|
padding: 0.75rem 1rem;
|
|
border-radius: 8px;
|
|
font-size: 0.9rem;
|
|
pointer-events: none;
|
|
z-index: 100;
|
|
max-width: 280px;
|
|
box-shadow: 0 4px 20px rgba(0,0,0,0.3);
|
|
border: 1px solid rgba(255,107,53,0.3);
|
|
}
|
|
|
|
.d3-tooltip strong {
|
|
color: #FF6B35;
|
|
}
|
|
|
|
.config-tabs {
|
|
display: flex;
|
|
gap: 0.5rem;
|
|
margin-bottom: 1rem;
|
|
}
|
|
|
|
.config-tab {
|
|
padding: 0.75rem 1.5rem;
|
|
background: #3a3a3a;
|
|
border: none;
|
|
border-radius: 8px 8px 0 0;
|
|
color: #b0b0b0;
|
|
cursor: pointer;
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.config-tab.active {
|
|
background: #FF6B35;
|
|
color: #fff;
|
|
}
|
|
|
|
.config-content {
|
|
display: none;
|
|
}
|
|
|
|
.config-content.active {
|
|
display: block;
|
|
}
|
|
|
|
.fade-in {
|
|
opacity: 0;
|
|
transform: translateY(20px);
|
|
transition: opacity 0.6s ease, transform 0.6s ease;
|
|
}
|
|
|
|
.fade-in.visible {
|
|
opacity: 1;
|
|
transform: translateY(0);
|
|
}
|
|
|
|
@media (max-width: 768px) {
|
|
.toc-list {
|
|
columns: 1;
|
|
}
|
|
|
|
.pillar-meta {
|
|
flex-direction: column;
|
|
gap: 0.5rem;
|
|
}
|
|
|
|
.chart-container {
|
|
min-height: 300px;
|
|
}
|
|
|
|
.pros-cons {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
|
|
.provider-grid {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
|
|
.config-tabs {
|
|
flex-wrap: wrap;
|
|
}
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div id="header"><header class="site-header"><nav class="navbar"><div class="container"><div class="nav-brand"><a href="/fr/" class="logo"><span class="logo-text">Odoo Expertos</span></a></div><button class="nav-toggle" aria-label="Toggle navigation"><span></span><span></span><span></span></button><div class="nav-menu"><ul class="nav-list"><li><a href="/fr/">Accueil</a></li><li><a href="/fr/odoo/">Odoo</a></li><li><a href="/fr/odoo-ia/">Odoo IA</a></li><li><a href="/fr/odoo-hosting/">Hebergement Odoo</a></li><li><a href="/fr/mapa-del-sitio/">Plan du Site</a></li></ul></div></div></nav></header></div><button class="nav-toggle" aria-label="Toggle navigation"><span></span><span></span><span></span></button><div class="nav-menu"><ul class="nav-list"><li><a href="/fr/">Accueil</a></li><li><a href="/fr/odoo/">Odoo</a></li><li><a href="/fr/odoo-ia/">Odoo IA</a></li><li><a href="/fr/odoo-hosting/">Hebergement Odoo</a></li><li><a href="/fr/mapa-del-sitio/">Plan du Site</a></li></ul></div></div></nav></header></div>
|
|
|
|
<!-- Breadcrumbs -->
|
|
<nav class="breadcrumbs">
|
|
<div class="container">
|
|
<ol class="breadcrumb-list" itemscope itemtype="https://schema.org/BreadcrumbList">
|
|
<li itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem">
|
|
<a itemprop="item" href="/"><span itemprop="name">Accueil</span></a>
|
|
<span itemprop="position" style="display:none">1</span>
|
|
</li>
|
|
<li itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem">
|
|
<a itemprop="item" href="/fr/odoo-hosting/"><span itemprop="name">Hébergement Odoo</span></a>
|
|
<span itemprop="position" style="display:none">2</span>
|
|
</li>
|
|
<li itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem">
|
|
<span itemprop="name">VPS Odoo Hosting 2026</span>
|
|
<span itemprop="position" style="display:none">3</span>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
</nav>
|
|
|
|
<!-- Hero Section -->
|
|
<section class="pillar-hero">
|
|
<div class="container">
|
|
<h1>VPS Odoo Hosting Guia 2026: Instalacion y Configuracion Completa</h1>
|
|
<p class="pillar-subtitle">Guia tecnica definitiva pour instalar Odoo en un VPS. Compourmos Hetzner, DigitalOcean, Vultr y Contabo con instrucciones paso a paso, optimizacion de rendimiento y hardening de seguridad.</p>
|
|
<div class="pillar-meta">
|
|
<span>Publié : 25 janvier 2026</span>
|
|
<span>Mis à jour : 25 janvier 2026</span>
|
|
<span>30 min lectura</span>
|
|
<span>Dr. Equipo Odoo Expertos</span>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<main class="container">
|
|
<!-- Quick Stats -->
|
|
<section class="quick-stats fade-in">
|
|
<div class="stat-card">
|
|
<span class="stat-number">4</span>
|
|
<span class="stat-label">Proveedores Analizados</span>
|
|
</div>
|
|
<div class="stat-card">
|
|
<span class="stat-number">4.51EUR</span>
|
|
<span class="stat-label">Prix Minimum/Mois</span>
|
|
</div>
|
|
<div class="stat-card">
|
|
<span class="stat-number">45min</span>
|
|
<span class="stat-label">Tiempo Instalacion</span>
|
|
</div>
|
|
<div class="stat-card">
|
|
<span class="stat-number">99.9%</span>
|
|
<span class="stat-label">Uptime Garantizado</span>
|
|
</div>
|
|
<div class="stat-card">
|
|
<span class="stat-number">32+</span>
|
|
<span class="stat-label">Ubicaciones Globales</span>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Table of Contents -->
|
|
<nav class="toc fade-in">
|
|
<h2>Contenido de esta Guia</h2>
|
|
<ol class="toc-list">
|
|
<li><a href="#introduccion">Por que Elegir VPS pour Odoo</a></li>
|
|
<li><a href="#compourtiva-vps">Compourtiva de Proveedores VPS</a></li>
|
|
<li><a href="#grafico-compourcion">Grafico: Precio vs Rendimiento</a></li>
|
|
<li><a href="#sizing-guide">Guia de Dimensionamiento</a></li>
|
|
<li><a href="#decision-tree">Arbol de Decision Interactivo</a></li>
|
|
<li><a href="#instalacion">Instalacion Paso a Paso</a></li>
|
|
<li><a href="#configuracion">Configuracion del Servidor</a></li>
|
|
<li><a href="#optimizacion">Optimizacion de Rendimiento</a></li>
|
|
<li><a href="#seguridad">Hardening de Seguridad</a></li>
|
|
<li><a href="#backups">Estrategia de Backups</a></li>
|
|
<li><a href="#faq">Preguntas Frecuentes</a></li>
|
|
</ol>
|
|
</nav>
|
|
|
|
<!-- Introduction -->
|
|
<section id="introduccion" class="content-section fade-in">
|
|
<h2>Por que Elegir VPS pour Odoo en 2026</h2>
|
|
|
|
<p>Un Servidor Virtual Privado (VPS) representa el equilibrio perfecto entre el control total de un servidor dedicado y la accesibilidad economica del hosting compartido. Pour Odoo, un VPS ofrece la flexibilidad necesaria pour personalizar cada aspecto del entorno de ejecucion, desde la version de Python hasta la configuracion de PostgreSQL.</p>
|
|
|
|
<p>En 2026, los proveedores de VPS han evolucionado significativamente, ofreciendo almacenamiento NVMe ultrarapido, redes de baja latencia y herramientas de gestion simplificadas. Esto hace que desplegar Odoo en un VPS sea mas accesible que nunca, incluso pour equipos con conocimientos tecnicos intermedios.</p>
|
|
|
|
<div class="highlight-box">
|
|
<h4>Resumen Ejecutivo</h4>
|
|
<p>Pour la mayoria de implementaciones de Odoo, recomendamos <strong>Hetzner Cloud</strong> por su excelente relacion precio-rendimiento en Europe. Si tu audiencia principal esta en America, considera <strong>DigitalOcean</strong> o <strong>Vultr</strong> por su presencia geografica. <strong>Contabo</strong> es ideal pour presupuestos muy ajustados donde el rendimiento no es critico.</p>
|
|
</div>
|
|
|
|
<h3>Ventajas de VPS sobre Hosting Gestionado</h3>
|
|
<div class="pros-cons">
|
|
<div class="pros">
|
|
<h4>Ventajas del VPS</h4>
|
|
<ul>
|
|
<li>Control total sobre el servidor</li>
|
|
<li>Sin limite de usuarios</li>
|
|
<li>Personalizacion completa</li>
|
|
<li>Coste fijo predecible</li>
|
|
<li>Instalacion de modulos sin restricciones</li>
|
|
<li>Acceso root completo</li>
|
|
</ul>
|
|
</div>
|
|
<div class="cons">
|
|
<h4>Desventajas del VPS</h4>
|
|
<ul>
|
|
<li>Requiere conocimientos tecnicos</li>
|
|
<li>Responsabilidad de mantenimiento</li>
|
|
<li>Configuracion manual de seguridad</li>
|
|
<li>Sin soporte Odoo incluido</li>
|
|
<li>Backups bajo tu responsabilidad</li>
|
|
<li>Tiempo de administracion</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
<h3>Cuando NO Elegir VPS</h3>
|
|
<p>Un VPS no es la mejor opcion si:</p>
|
|
<ul>
|
|
<li>No tienes experiencia con Linux y linea de comandos</li>
|
|
<li>Necesitas soporte tecnico especializado en Odoo</li>
|
|
<li>Prefieres actualizaciones automaticas gestionadas</li>
|
|
<li>Tu tiempo es mas valioso que el ahorro en hosting</li>
|
|
<li>Requieres SLA garantizado con compensacion</li>
|
|
</ul>
|
|
<p>En estos casos, considera <a href="/fr/odoo-hosting/mejor-hosting-odoo-2026/">hosting gestionado</a> como Odoo4projects u Odoo.sh.</p>
|
|
</section>
|
|
|
|
<!-- Provider Comparison -->
|
|
<section id="compourtiva-vps" class="content-section fade-in">
|
|
<h2>Compourtiva de Proveedores VPS pour Odoo</h2>
|
|
|
|
<p>Analizamos los cuatro proveedores VPS mas populares pour Odoo, evaluando precio, rendimiento, ubicaciones y caracteristicas especificas pour cargas de trabajo ERP.</p>
|
|
|
|
<div style="overflow-x: auto;">
|
|
<table class="comparison-table">
|
|
<thead>
|
|
<tr>
|
|
<th>Proveedor</th>
|
|
<th>Plan Minimo Odoo</th>
|
|
<th>RAM</th>
|
|
<th>CPU</th>
|
|
<th>SSD</th>
|
|
<th>Ubicaciones</th>
|
|
<th>Rating</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td><strong>Hetzner Cloud</strong></td>
|
|
<td>7.05EUR/mes (CX22)</td>
|
|
<td>4 GB</td>
|
|
<td>2 vCPU</td>
|
|
<td>40 GB NVMe</td>
|
|
<td>5 (EU/US)</td>
|
|
<td>4.8/5</td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong>DigitalOcean</strong></td>
|
|
<td>$24/mes (4GB)</td>
|
|
<td>4 GB</td>
|
|
<td>2 vCPU</td>
|
|
<td>80 GB SSD</td>
|
|
<td>15</td>
|
|
<td>4.6/5</td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong>Vultr</strong></td>
|
|
<td>$24/mes (4GB)</td>
|
|
<td>4 GB</td>
|
|
<td>2 vCPU</td>
|
|
<td>100 GB NVMe</td>
|
|
<td>32</td>
|
|
<td>4.5/5</td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong>Contabo</strong></td>
|
|
<td>5.99EUR/mes (VPS S)</td>
|
|
<td>8 GB</td>
|
|
<td>4 vCPU</td>
|
|
<td>200 GB SSD</td>
|
|
<td>6</td>
|
|
<td>4.1/5</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<!-- Provider Cards -->
|
|
<div class="provider-grid">
|
|
<!-- Hetzner -->
|
|
<div class="provider-card featured">
|
|
<span class="badge">Recommandé</span>
|
|
<h4>Hetzner Cloud</h4>
|
|
<p class="price">7.05EUR<span class="price-period">/mes (CX22)</span></p>
|
|
<ul>
|
|
<li>Mejor rendimiento por euro en Europe</li>
|
|
<li>Almacenamiento NVMe ultrarapido</li>
|
|
<li>Centros de datos en Alemania y Finlandia</li>
|
|
<li>Nueva ubicacion en EE.UU. (Ashburn)</li>
|
|
<li>API completa y bien documentada</li>
|
|
<li>Snapshots y backups automaticos</li>
|
|
<li>IPv6 nativo incluido</li>
|
|
</ul>
|
|
<div class="pros-cons">
|
|
<div class="pros">
|
|
<h4>Ventajas</h4>
|
|
<ul>
|
|
<li>Precio imbatible en Europe</li>
|
|
<li>Excelente rendimiento I/O</li>
|
|
<li>Facturacion por hora</li>
|
|
</ul>
|
|
</div>
|
|
<div class="cons">
|
|
<h4>Limitaciones</h4>
|
|
<ul>
|
|
<li>Soporte solo en ingles/aleman</li>
|
|
<li>Pocas ubicaciones fuera de Europe</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<a href="https://hetzner.cloud" class="cta-btn" target="_blank" rel="noopener">Ver Planes Hetzner</a>
|
|
</div>
|
|
|
|
<!-- DigitalOcean -->
|
|
<div class="provider-card">
|
|
<h4>DigitalOcean</h4>
|
|
<p class="price">$24<span class="price-period">/mes (4GB Droplet)</span></p>
|
|
<ul>
|
|
<li>Documentacion excepcional</li>
|
|
<li>Comunidad muy activa</li>
|
|
<li>Marketplace con apps preconfiguradas</li>
|
|
<li>15 ubicaciones globales</li>
|
|
<li>Panel de control intuitivo</li>
|
|
<li>Monitoreo integrado</li>
|
|
<li>$200 credito pour nuevos usuarios</li>
|
|
</ul>
|
|
<a href="https://digitalocean.com" class="cta-btn" target="_blank" rel="noopener">Ver Planes DO</a>
|
|
</div>
|
|
|
|
<!-- Vultr -->
|
|
<div class="provider-card">
|
|
<h4>Vultr</h4>
|
|
<p class="price">$24<span class="price-period">/mes (4GB Cloud)</span></p>
|
|
<ul>
|
|
<li>32 ubicaciones en todo el mundo</li>
|
|
<li>Almacenamiento NVMe en todos los planes</li>
|
|
<li>Bare metal disponible</li>
|
|
<li>Kubernetes gestionado</li>
|
|
<li>Excelente latencia global</li>
|
|
<li>Facturacion por hora</li>
|
|
<li>$250 credito promocional</li>
|
|
</ul>
|
|
<a href="https://vultr.com" class="cta-btn" target="_blank" rel="noopener">Ver Planes Vultr</a>
|
|
</div>
|
|
|
|
<!-- Contabo -->
|
|
<div class="provider-card">
|
|
<span class="badge">Economico</span>
|
|
<h4>Contabo</h4>
|
|
<p class="price">5.99EUR<span class="price-period">/mes (VPS S)</span></p>
|
|
<ul>
|
|
<li>Recursos muy generosos por precio</li>
|
|
<li>8 GB RAM en plan basico</li>
|
|
<li>200 GB SSD incluidos</li>
|
|
<li>Sin limite de trafico</li>
|
|
<li>Centros de datos en EU/US/Asia</li>
|
|
<li>Snapshots opcionales</li>
|
|
</ul>
|
|
<div class="warning-box">
|
|
<h4>Nota sobre Contabo</h4>
|
|
<p>Contabo ofrece excelentes recursos por precio, pero el rendimiento puede ser inferior a otros proveedores debido a overselling. Recommandé pour desarrollo o proyectos no criticos.</p>
|
|
</div>
|
|
<a href="https://contabo.com" class="cta-btn" target="_blank" rel="noopener">Ver Planes Contabo</a>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- D3.js Comparison Chart -->
|
|
<section class="chart-section fade-in">
|
|
<h3 id="grafico-compourcion">Compourtiva Visual: Precio vs Rendimiento</h3>
|
|
<p>Este grafico interactivo compour los proveedores VPS en terminos de precio mensual frente a puntuacion de rendimiento. El tamano del circulo indica la cantidad de ubicaciones disponibles.</p>
|
|
<div class="chart-container" id="vps-scatter-chart"></div>
|
|
</section>
|
|
|
|
<!-- Sizing Guide -->
|
|
<section id="sizing-guide" class="content-section fade-in">
|
|
<h2>Guia de Dimensionamiento: Que VPS Necesitas</h2>
|
|
|
|
<p>El dimensionamiento correcto del servidor es crucial pour el rendimiento de Odoo. Un servidor subdimensionado causara lentitud y frustracion, mientras que uno sobredimensionado desperdicia recursos.</p>
|
|
|
|
<h3>Regla General de Dimensionamiento</h3>
|
|
<div class="info-box">
|
|
<h4>Formula Basica</h4>
|
|
<p><strong>RAM necesaria = 2GB base + (0.3GB x usuarios simultaneos)</strong></p>
|
|
<p><strong>Workers = (CPU cores x 2) + 1</strong></p>
|
|
<p><strong>Almacenamiento = 20GB base + (2GB x usuarios totales) + espacio filestore</strong></p>
|
|
</div>
|
|
|
|
<table class="comparison-table">
|
|
<thead>
|
|
<tr>
|
|
<th>Escenario</th>
|
|
<th>Usuarios Simultaneos</th>
|
|
<th>RAM Minima</th>
|
|
<th>CPU</th>
|
|
<th>Almacenamiento</th>
|
|
<th>Plan Recommandé</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td><strong>Desarrollo/Pruebas</strong></td>
|
|
<td>1-3</td>
|
|
<td>2 GB</td>
|
|
<td>1 vCPU</td>
|
|
<td>20 GB</td>
|
|
<td>Hetzner CX11 (3.29EUR)</td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong>Startup Pequena</strong></td>
|
|
<td>5-10</td>
|
|
<td>4 GB</td>
|
|
<td>2 vCPU</td>
|
|
<td>40 GB</td>
|
|
<td>Hetzner CX22 (7.05EUR)</td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong>PYME</strong></td>
|
|
<td>10-25</td>
|
|
<td>8 GB</td>
|
|
<td>4 vCPU</td>
|
|
<td>80 GB</td>
|
|
<td>Hetzner CX32 (13.10EUR)</td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong>Empresa Mediana</strong></td>
|
|
<td>25-50</td>
|
|
<td>16 GB</td>
|
|
<td>8 vCPU</td>
|
|
<td>160 GB</td>
|
|
<td>Hetzner CX42 (25.40EUR)</td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong>Enterprise</strong></td>
|
|
<td>50-100+</td>
|
|
<td>32 GB+</td>
|
|
<td>16 vCPU+</td>
|
|
<td>320 GB+</td>
|
|
<td>Hetzner CX52 (49.90EUR)</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
|
|
<h3>Consideraciones Adicionales</h3>
|
|
<ul>
|
|
<li><strong>Odoo Enterprise:</strong> Requiere aproximadamente 50% mas de RAM que Community</li>
|
|
<li><strong>Muchos modulos:</strong> Cada modulo adicional consume memoria. Con 20+ modulos, aumenta RAM un 25%</li>
|
|
<li><strong>Integraciones API:</strong> Si usas integraciones intensivas, considera mas CPU</li>
|
|
<li><strong>Filestore grande:</strong> Archivos adjuntos y documentos pueden requerir mucho espacio</li>
|
|
<li><strong>PostgreSQL sepourdo:</strong> Pour cargas altas, considera sepourr la base de datos en otro servidor</li>
|
|
</ul>
|
|
</section>
|
|
|
|
<!-- D3.js Decision Tree -->
|
|
<section class="chart-section fade-in">
|
|
<h3 id="decision-tree">Arbol de Decision: Elige tu VPS</h3>
|
|
<p>Navega por este arbol interactivo pour encontrar el proveedor VPS ideal segun tus necesidades especificas.</p>
|
|
<div class="chart-container" id="vps-decision-tree"></div>
|
|
</section>
|
|
|
|
<!-- Installation Guide -->
|
|
<section id="instalacion" class="content-section fade-in">
|
|
<h2>Instalacion de Odoo 18 en VPS: Guia Paso a Paso</h2>
|
|
|
|
<p>Esta guia asume que estas usando Ubuntu 22.04 LTS o 24.04 LTS. Las instrucciones son validas pour cualquier proveedor VPS.</p>
|
|
|
|
<div class="warning-box">
|
|
<h4>Antes de Empezar</h4>
|
|
<p>Asegurate de tener: acceso SSH root a tu VPS, un dominio apuntando a la IP del servidor, y aproximadamente 45 minutos de tiempo.</p>
|
|
</div>
|
|
|
|
<ol class="step-list">
|
|
<li>
|
|
<h4>Actualizar el Sistema y Crear Usuario</h4>
|
|
<p>Primero, actualiza todos los paquetes y crea un usuario dedicado pour Odoo:</p>
|
|
<div class="code-block">
|
|
<code>
|
|
<span class="comment"># Actualizar sistema</span>
|
|
<span class="command">sudo apt update && sudo apt upgrade -y</span>
|
|
|
|
<span class="comment"># Crear usuario odoo</span>
|
|
<span class="command">sudo adduser --system --home=/opt/odoo --group odoo</span>
|
|
|
|
<span class="comment"># Instalar dependencias basicas</span>
|
|
<span class="command">sudo apt install -y git python3-pip python3-dev python3-venv \
|
|
libxml2-dev libxslt1-dev zlib1g-dev libsasl2-dev \
|
|
libldap2-dev build-essential libssl-dev libffi-dev \
|
|
libmysqlclient-dev libjpeg-dev libpq-dev libjpeg8-dev \
|
|
liblcms2-dev libblas-dev libatlas-base-dev npm</span>
|
|
</code>
|
|
</div>
|
|
</li>
|
|
|
|
<li>
|
|
<h4>Instalar PostgreSQL 16</h4>
|
|
<p>Odoo requiere PostgreSQL como base de datos. Instalamos la version 16 pour mejor rendimiento:</p>
|
|
<div class="code-block">
|
|
<code>
|
|
<span class="comment"># Agregar repositorio oficial de PostgreSQL</span>
|
|
<span class="command">sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'</span>
|
|
<span class="command">wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -</span>
|
|
<span class="command">sudo apt update</span>
|
|
|
|
<span class="comment"># Instalar PostgreSQL 16</span>
|
|
<span class="command">sudo apt install -y postgresql-16 postgresql-client-16</span>
|
|
|
|
<span class="comment"># Crear usuario de base de datos pour Odoo</span>
|
|
<span class="command">sudo -u postgres createuser -s odoo</span>
|
|
</code>
|
|
</div>
|
|
</li>
|
|
|
|
<li>
|
|
<h4>Instalar wkhtmltopdf</h4>
|
|
<p>Necesario pour generar reportes PDF en Odoo:</p>
|
|
<div class="code-block">
|
|
<code>
|
|
<span class="comment"># Descargar e instalar wkhtmltopdf con soporte Qt</span>
|
|
<span class="command">wget https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6.1-3/wkhtmltox_0.12.6.1-3.jammy_amd64.deb</span>
|
|
<span class="command">sudo apt install -y ./wkhtmltox_0.12.6.1-3.jammy_amd64.deb</span>
|
|
<span class="command">rm wkhtmltox_0.12.6.1-3.jammy_amd64.deb</span>
|
|
</code>
|
|
</div>
|
|
</li>
|
|
|
|
<li>
|
|
<h4>Descargar e Instalar Odoo 18</h4>
|
|
<p>Clonamos el repositorio oficial y configuramos el entorno:</p>
|
|
<div class="code-block">
|
|
<code>
|
|
<span class="comment"># Clonar Odoo 18</span>
|
|
<span class="command">sudo git clone --depth 1 --branch 18.0 https://github.com/odoo/odoo.git /opt/odoo/odoo</span>
|
|
|
|
<span class="comment"># Crear entorno virtual Python</span>
|
|
<span class="command">sudo python3 -m venv /opt/odoo/venv</span>
|
|
|
|
<span class="comment"># Instalar dependencias de Odoo</span>
|
|
<span class="command">sudo /opt/odoo/venv/bin/pip install wheel</span>
|
|
<span class="command">sudo /opt/odoo/venv/bin/pip install -r /opt/odoo/odoo/requirements.txt</span>
|
|
|
|
<span class="comment"># Crear directorio pour modulos personalizados</span>
|
|
<span class="command">sudo mkdir /opt/odoo/custom-addons</span>
|
|
|
|
<span class="comment"># Establecer permisos</span>
|
|
<span class="command">sudo chown -R odoo:odoo /opt/odoo</span>
|
|
</code>
|
|
</div>
|
|
</li>
|
|
|
|
<li>
|
|
<h4>Crear Archivo de Configuracion</h4>
|
|
<p>Configuramos Odoo con pourmetros optimizados:</p>
|
|
<div class="code-block">
|
|
<code>
|
|
<span class="command">sudo nano /etc/odoo.conf</span>
|
|
</code>
|
|
</div>
|
|
<p>Contenido del archivo:</p>
|
|
<div class="code-block">
|
|
<code>
|
|
<span class="variable">[options]</span>
|
|
<span class="comment">; Configuracion basica</span>
|
|
admin_passwd = <span class="string">TuContraseñaSeguraAqui123!</span>
|
|
db_host = False
|
|
db_port = False
|
|
db_user = odoo
|
|
db_password = False
|
|
|
|
<span class="comment">; Rutas</span>
|
|
addons_path = /opt/odoo/odoo/addons,/opt/odoo/custom-addons
|
|
data_dir = /opt/odoo/.local/share/Odoo
|
|
|
|
<span class="comment">; Servidor</span>
|
|
http_port = 8069
|
|
longpolling_port = 8072
|
|
proxy_mode = True
|
|
|
|
<span class="comment">; Workers (ajustar segun CPU)</span>
|
|
workers = 4
|
|
max_cron_threads = 2
|
|
|
|
<span class="comment">; Limites de memoria (ajustar segun RAM)</span>
|
|
limit_memory_hard = 2684354560
|
|
limit_memory_soft = 2147483648
|
|
limit_time_cpu = 600
|
|
limit_time_real = 1200
|
|
|
|
<span class="comment">; Logs</span>
|
|
logfile = /var/log/odoo/odoo.log
|
|
log_level = warn
|
|
</code>
|
|
</div>
|
|
</li>
|
|
|
|
<li>
|
|
<h4>Crear Servicio Systemd</h4>
|
|
<p>Configuramos Odoo como servicio del sistema:</p>
|
|
<div class="code-block">
|
|
<code>
|
|
<span class="command">sudo nano /etc/systemd/system/odoo.service</span>
|
|
</code>
|
|
</div>
|
|
<p>Contenido:</p>
|
|
<div class="code-block">
|
|
<code>
|
|
<span class="variable">[Unit]</span>
|
|
Description=Odoo 18
|
|
After=network.target postgresql.service
|
|
|
|
<span class="variable">[Service]</span>
|
|
Type=simple
|
|
SyslogIdentifier=odoo
|
|
PermissionsStartOnly=true
|
|
User=odoo
|
|
Group=odoo
|
|
ExecStart=/opt/odoo/venv/bin/python3 /opt/odoo/odoo/odoo-bin -c /etc/odoo.conf
|
|
StandardOutput=journal+console
|
|
Restart=always
|
|
RestartSec=5
|
|
|
|
<span class="variable">[Install]</span>
|
|
WantedBy=multi-user.target
|
|
</code>
|
|
</div>
|
|
<div class="code-block">
|
|
<code>
|
|
<span class="comment"># Crear directorio de logs</span>
|
|
<span class="command">sudo mkdir -p /var/log/odoo</span>
|
|
<span class="command">sudo chown odoo:odoo /var/log/odoo</span>
|
|
|
|
<span class="comment"># Habilitar e iniciar servicio</span>
|
|
<span class="command">sudo systemctl daemon-reload</span>
|
|
<span class="command">sudo systemctl enable odoo</span>
|
|
<span class="command">sudo systemctl start odoo</span>
|
|
|
|
<span class="comment"># Verificar estado</span>
|
|
<span class="command">sudo systemctl status odoo</span>
|
|
</code>
|
|
</div>
|
|
</li>
|
|
|
|
<li>
|
|
<h4>Instalar y Configurar Nginx</h4>
|
|
<p>Configuramos Nginx como proxy inverso con SSL:</p>
|
|
<div class="code-block">
|
|
<code>
|
|
<span class="comment"># Instalar Nginx y Certbot</span>
|
|
<span class="command">sudo apt install -y nginx certbot python3-certbot-nginx</span>
|
|
|
|
<span class="comment"># Crear configuracion de Nginx</span>
|
|
<span class="command">sudo nano /etc/nginx/sites-available/odoo</span>
|
|
</code>
|
|
</div>
|
|
<p>Contenido del archivo Nginx:</p>
|
|
<div class="code-block">
|
|
<code>
|
|
upstream odoo {
|
|
server 127.0.0.1:8069;
|
|
}
|
|
|
|
upstream odoochat {
|
|
server 127.0.0.1:8072;
|
|
}
|
|
|
|
server {
|
|
listen 80;
|
|
server_name <span class="string">tu-dominio.com</span>;
|
|
|
|
<span class="comment"># Redirigir a HTTPS</span>
|
|
return 301 https://$server_name$request_uri;
|
|
}
|
|
|
|
server {
|
|
listen 443 ssl http2;
|
|
server_name <span class="string">tu-dominio.com</span>;
|
|
|
|
<span class="comment"># Logs</span>
|
|
access_log /var/log/nginx/odoo.access.log;
|
|
error_log /var/log/nginx/odoo.error.log;
|
|
|
|
<span class="comment"># SSL (Certbot lo configurara)</span>
|
|
ssl_certificate /etc/letsencrypt/live/tu-dominio.com/fullchain.pem;
|
|
ssl_certificate_key /etc/letsencrypt/live/tu-dominio.com/privkey.pem;
|
|
|
|
<span class="comment"># Proxy settings</span>
|
|
proxy_read_timeout 720s;
|
|
proxy_connect_timeout 720s;
|
|
proxy_send_timeout 720s;
|
|
|
|
<span class="comment"># Headers</span>
|
|
proxy_set_header X-Forwarded-Host $host;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
proxy_set_header X-Forwarded-Proto $scheme;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
|
|
<span class="comment"># Longpolling</span>
|
|
location /longpolling {
|
|
proxy_pass http://odoochat;
|
|
}
|
|
|
|
<span class="comment"># Archivos estaticos</span>
|
|
location ~* /web/static/ {
|
|
proxy_cache_valid 200 90m;
|
|
proxy_buffering on;
|
|
expires 864000;
|
|
proxy_pass http://odoo;
|
|
}
|
|
|
|
<span class="comment"># Proxy principal</span>
|
|
location / {
|
|
proxy_redirect off;
|
|
proxy_pass http://odoo;
|
|
}
|
|
|
|
<span class="comment"># Gzip</span>
|
|
gzip_types text/css text/plain text/xml application/xml application/javascript application/x-javascript text/javascript;
|
|
gzip on;
|
|
}
|
|
</code>
|
|
</div>
|
|
<div class="code-block">
|
|
<code>
|
|
<span class="comment"># Habilitar sitio</span>
|
|
<span class="command">sudo ln -s /etc/nginx/sites-available/odoo /etc/nginx/sites-enabled/</span>
|
|
<span class="command">sudo rm /etc/nginx/sites-enabled/default</span>
|
|
|
|
<span class="comment"># Obtener certificado SSL</span>
|
|
<span class="command">sudo certbot --nginx -d tu-dominio.com</span>
|
|
|
|
<span class="comment"># Reiniciar Nginx</span>
|
|
<span class="command">sudo nginx -t && sudo systemctl restart nginx</span>
|
|
</code>
|
|
</div>
|
|
</li>
|
|
</ol>
|
|
|
|
<div class="success-box">
|
|
<h4>Instalacion Completada</h4>
|
|
<p>Ahora puedes acceder a Odoo en <strong>https://tu-dominio.com</strong>. La primera vez, crea la base de datos usando la contrasena maestra que configuraste en odoo.conf.</p>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Server Configuration -->
|
|
<section id="configuracion" class="content-section fade-in">
|
|
<h2>Configuracion Avanzada del Servidor</h2>
|
|
|
|
<h3>Optimizacion de PostgreSQL pour Odoo</h3>
|
|
<p>PostgreSQL viene con configuracion conservadora por defecto. Ajustamos pour mejor rendimiento:</p>
|
|
|
|
<div class="code-block">
|
|
<code>
|
|
<span class="command">sudo nano /etc/postgresql/16/main/postgresql.conf</span>
|
|
</code>
|
|
</div>
|
|
|
|
<p>Pourmetros recomendados pour servidor de 8GB RAM:</p>
|
|
|
|
<div class="code-block">
|
|
<code>
|
|
<span class="comment"># Memoria</span>
|
|
shared_buffers = <span class="string">2GB</span> <span class="comment"># 25% de RAM</span>
|
|
effective_cache_size = <span class="string">6GB</span> <span class="comment"># 75% de RAM</span>
|
|
work_mem = <span class="string">64MB</span> <span class="comment"># RAM / max_connections / 2</span>
|
|
maintenance_work_mem = <span class="string">512MB</span>
|
|
|
|
<span class="comment"># Checkpoint</span>
|
|
checkpoint_completion_target = <span class="string">0.9</span>
|
|
wal_buffers = <span class="string">64MB</span>
|
|
default_statistics_target = <span class="string">100</span>
|
|
|
|
<span class="comment"># Planificador</span>
|
|
random_page_cost = <span class="string">1.1</span> <span class="comment"># Pour SSD</span>
|
|
effective_io_concurrency = <span class="string">200</span> <span class="comment"># Pour SSD</span>
|
|
|
|
<span class="comment"># Conexiones</span>
|
|
max_connections = <span class="string">100</span>
|
|
|
|
<span class="comment"># Logs</span>
|
|
log_min_duration_statement = <span class="string">1000</span> <span class="comment"># Log queries lentas (+1s)</span>
|
|
</code>
|
|
</div>
|
|
|
|
<div class="code-block">
|
|
<code>
|
|
<span class="comment"># Reiniciar PostgreSQL</span>
|
|
<span class="command">sudo systemctl restart postgresql</span>
|
|
</code>
|
|
</div>
|
|
|
|
<h3>Configuracion de Workers de Odoo</h3>
|
|
<p>La configuracion de workers es critica pour el rendimiento. Usa esta formula:</p>
|
|
|
|
<div class="info-box">
|
|
<h4>Calculo de Workers</h4>
|
|
<p><strong>workers = (CPU cores * 2) + 1</strong></p>
|
|
<p><strong>max_cron_threads = 2</strong> (maximo)</p>
|
|
<p><strong>limit_memory_soft = 640MB por worker</strong></p>
|
|
<p><strong>limit_memory_hard = 768MB por worker</strong></p>
|
|
</div>
|
|
|
|
<table class="comparison-table">
|
|
<thead>
|
|
<tr>
|
|
<th>CPU Cores</th>
|
|
<th>Workers</th>
|
|
<th>RAM Necesaria</th>
|
|
<th>Usuarios Simultaneos</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr><td>2</td><td>5</td><td>4 GB</td><td>10-15</td></tr>
|
|
<tr><td>4</td><td>9</td><td>8 GB</td><td>20-30</td></tr>
|
|
<tr><td>8</td><td>17</td><td>16 GB</td><td>40-60</td></tr>
|
|
<tr><td>16</td><td>33</td><td>32 GB</td><td>80-120</td></tr>
|
|
</tbody>
|
|
</table>
|
|
</section>
|
|
|
|
<!-- Performance Optimization -->
|
|
<section id="optimizacion" class="content-section fade-in">
|
|
<h2>Optimizacion de Rendimiento</h2>
|
|
|
|
<h3>1. Habilitar Swap (Recommandé)</h3>
|
|
<p>Swap proporciona un colchon de seguridad cuando la RAM se agota:</p>
|
|
<div class="code-block">
|
|
<code>
|
|
<span class="comment"># Crear archivo swap de 4GB</span>
|
|
<span class="command">sudo fallocate -l 4G /swapfile</span>
|
|
<span class="command">sudo chmod 600 /swapfile</span>
|
|
<span class="command">sudo mkswap /swapfile</span>
|
|
<span class="command">sudo swapon /swapfile</span>
|
|
|
|
<span class="comment"># Hacer permanente</span>
|
|
<span class="command">echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab</span>
|
|
|
|
<span class="comment"># Ajustar swappiness pour servidores</span>
|
|
<span class="command">echo 'vm.swappiness=10' | sudo tee -a /etc/sysctl.conf</span>
|
|
<span class="command">sudo sysctl -p</span>
|
|
</code>
|
|
</div>
|
|
|
|
<h3>2. Cache de Assets con Nginx</h3>
|
|
<p>Mejora tiempos de carga cacheando archivos estaticos:</p>
|
|
<div class="code-block">
|
|
<code>
|
|
<span class="comment"># Agregar a la seccion server de Nginx</span>
|
|
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
|
|
expires 30d;
|
|
add_header Cache-Control "public, immutable";
|
|
proxy_pass http://odoo;
|
|
}
|
|
</code>
|
|
</div>
|
|
|
|
<h3>3. Compresion Gzip</h3>
|
|
<p>Reduce el tamano de transferencia significativamente:</p>
|
|
<div class="code-block">
|
|
<code>
|
|
<span class="comment"># En /etc/nginx/nginx.conf</span>
|
|
gzip on;
|
|
gzip_vary on;
|
|
gzip_proxied any;
|
|
gzip_comp_level 6;
|
|
gzip_types text/plain text/css text/xml application/json application/javascript
|
|
application/xml application/xml+rss text/javascript application/x-javascript;
|
|
gzip_min_length 1000;
|
|
</code>
|
|
</div>
|
|
|
|
<h3>4. Indices de Base de Datos</h3>
|
|
<p>Crea indices adicionales pour consultas frecuentes:</p>
|
|
<div class="code-block">
|
|
<code>
|
|
<span class="comment"># Conectar a PostgreSQL</span>
|
|
<span class="command">sudo -u postgres psql nombre_base_datos</span>
|
|
|
|
<span class="comment"># Indices utiles pour Odoo</span>
|
|
CREATE INDEX CONCURRENTLY idx_mail_message_date ON mail_message(date DESC);
|
|
CREATE INDEX CONCURRENTLY idx_sale_order_state ON sale_order(state);
|
|
CREATE INDEX CONCURRENTLY idx_purchase_order_state ON purchase_order(state);
|
|
CREATE INDEX CONCURRENTLY idx_stock_move_state ON stock_move(state);
|
|
</code>
|
|
</div>
|
|
|
|
<h3>5. Programar VACUUM y ANALYZE</h3>
|
|
<p>Mantiene PostgreSQL optimizado:</p>
|
|
<div class="code-block">
|
|
<code>
|
|
<span class="comment"># Agregar al crontab del usuario postgres</span>
|
|
<span class="command">sudo crontab -u postgres -e</span>
|
|
|
|
<span class="comment"># Ejecutar VACUUM cada noche a las 3 AM</span>
|
|
0 3 * * * /usr/bin/vacuumdb -a -z -q
|
|
</code>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Security Hardening -->
|
|
<section id="seguridad" class="content-section fade-in">
|
|
<h2>Hardening de Seguridad</h2>
|
|
|
|
<p>La seguridad es critica pour cualquier servidor en produccion. Implementamos multiples capas de proteccion.</p>
|
|
|
|
<h3>1. Configurar Firewall (UFW)</h3>
|
|
<div class="code-block">
|
|
<code>
|
|
<span class="comment"># Instalar y configurar UFW</span>
|
|
<span class="command">sudo apt install -y ufw</span>
|
|
|
|
<span class="comment"># Politicas por defecto</span>
|
|
<span class="command">sudo ufw default deny incoming</span>
|
|
<span class="command">sudo ufw default allow outgoing</span>
|
|
|
|
<span class="comment"># Permitir SSH (IMPORTANTE: no bloquear tu acceso)</span>
|
|
<span class="command">sudo ufw allow 22/tcp</span>
|
|
|
|
<span class="comment"># Permitir HTTP y HTTPS</span>
|
|
<span class="command">sudo ufw allow 80/tcp</span>
|
|
<span class="command">sudo ufw allow 443/tcp</span>
|
|
|
|
<span class="comment"># Habilitar firewall</span>
|
|
<span class="command">sudo ufw enable</span>
|
|
<span class="command">sudo ufw status</span>
|
|
</code>
|
|
</div>
|
|
|
|
<h3>2. Securizar SSH</h3>
|
|
<div class="code-block">
|
|
<code>
|
|
<span class="command">sudo nano /etc/ssh/sshd_config</span>
|
|
</code>
|
|
</div>
|
|
<p>Cambiar estas configuraciones:</p>
|
|
<div class="code-block">
|
|
<code>
|
|
<span class="comment"># Deshabilitar login root</span>
|
|
PermitRootLogin no
|
|
|
|
<span class="comment"># Usar solo autenticacion por clave</span>
|
|
PasswordAuthentication no
|
|
PubkeyAuthentication yes
|
|
|
|
<span class="comment"># Limitar intentos</span>
|
|
MaxAuthTries 3
|
|
|
|
<span class="comment"># Timeout de sesion inactiva</span>
|
|
ClientAliveInterval 300
|
|
ClientAliveCountMax 2
|
|
</code>
|
|
</div>
|
|
|
|
<div class="warning-box">
|
|
<h4>Importante</h4>
|
|
<p>Antes de deshabilitar PasswordAuthentication, asegurate de tener tu clave SSH configurada correctamente. De lo contrario, perderas acceso al servidor.</p>
|
|
</div>
|
|
|
|
<h3>3. Instalar Fail2ban</h3>
|
|
<p>Protege contra ataques de fuerza bruta:</p>
|
|
<div class="code-block">
|
|
<code>
|
|
<span class="command">sudo apt install -y fail2ban</span>
|
|
<span class="command">sudo nano /etc/fail2ban/jail.local</span>
|
|
</code>
|
|
</div>
|
|
<div class="code-block">
|
|
<code>
|
|
[DEFAULT]
|
|
bantime = 3600
|
|
findtime = 600
|
|
maxretry = 5
|
|
|
|
[sshd]
|
|
enabled = true
|
|
port = ssh
|
|
filter = sshd
|
|
logpath = /var/log/auth.log
|
|
maxretry = 3
|
|
|
|
[nginx-http-auth]
|
|
enabled = true
|
|
</code>
|
|
</div>
|
|
<div class="code-block">
|
|
<code>
|
|
<span class="command">sudo systemctl enable fail2ban</span>
|
|
<span class="command">sudo systemctl start fail2ban</span>
|
|
</code>
|
|
</div>
|
|
|
|
<h3>4. Actualizaciones Automaticas de Seguridad</h3>
|
|
<div class="code-block">
|
|
<code>
|
|
<span class="command">sudo apt install -y unattended-upgrades</span>
|
|
<span class="command">sudo dpkg-reconfigure -plow unattended-upgrades</span>
|
|
</code>
|
|
</div>
|
|
|
|
<h3>5. Limitar Acceso a la Base de Datos</h3>
|
|
<p>PostgreSQL solo debe ser accesible localmente:</p>
|
|
<div class="code-block">
|
|
<code>
|
|
<span class="command">sudo nano /etc/postgresql/16/main/pg_hba.conf</span>
|
|
|
|
<span class="comment"># Asegurar que solo permite conexiones locales</span>
|
|
local all all peer
|
|
host all all 127.0.0.1/32 scram-sha-256
|
|
</code>
|
|
</div>
|
|
|
|
<h3>6. Headers de Seguridad en Nginx</h3>
|
|
<div class="code-block">
|
|
<code>
|
|
<span class="comment"># Agregar al bloque server de Nginx</span>
|
|
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 "strict-origin-when-cross-origin" always;
|
|
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
|
</code>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Backup Strategy -->
|
|
<section id="backups" class="content-section fade-in">
|
|
<h2>Estrategia de Backups</h2>
|
|
|
|
<p>Una estrategia de backup solida es esencial. Debes respaldar tres componentes:</p>
|
|
|
|
<h3>Componentes a Respaldar</h3>
|
|
<ul>
|
|
<li><strong>Base de datos PostgreSQL:</strong> Todos los datos de Odoo</li>
|
|
<li><strong>Filestore:</strong> Archivos adjuntos, imagenes, documentos</li>
|
|
<li><strong>Configuracion:</strong> odoo.conf, nginx, etc.</li>
|
|
</ul>
|
|
|
|
<h3>Script de Backup Automatico</h3>
|
|
<div class="code-block">
|
|
<code>
|
|
<span class="command">sudo nano /opt/odoo/backup.sh</span>
|
|
</code>
|
|
</div>
|
|
<div class="code-block">
|
|
<code>
|
|
#!/bin/bash
|
|
|
|
<span class="comment"># Variables</span>
|
|
BACKUP_DIR="/opt/odoo/backups"
|
|
DATE=$(date +%Y%m%d_%H%M%S)
|
|
DB_NAME="tu_base_de_datos"
|
|
RETENTION_DAYS=30
|
|
|
|
<span class="comment"># Crear directorio si no existe</span>
|
|
mkdir -p $BACKUP_DIR
|
|
|
|
<span class="comment"># Backup de base de datos</span>
|
|
echo "Respaldando base de datos..."
|
|
sudo -u postgres pg_dump $DB_NAME | gzip > $BACKUP_DIR/db_${DATE}.sql.gz
|
|
|
|
<span class="comment"># Backup del filestore</span>
|
|
echo "Respaldando filestore..."
|
|
tar -czf $BACKUP_DIR/filestore_${DATE}.tar.gz /opt/odoo/.local/share/Odoo/filestore/$DB_NAME
|
|
|
|
<span class="comment"># Backup de configuracion</span>
|
|
echo "Respaldando configuracion..."
|
|
tar -czf $BACKUP_DIR/config_${DATE}.tar.gz /etc/odoo.conf /etc/nginx/sites-available/odoo
|
|
|
|
<span class="comment"># Eliminar backups antiguos</span>
|
|
find $BACKUP_DIR -type f -mtime +$RETENTION_DAYS -delete
|
|
|
|
<span class="comment"># Mostrar tamano de backups</span>
|
|
echo "Backup completado:"
|
|
ls -lh $BACKUP_DIR/*_${DATE}*
|
|
|
|
<span class="comment"># Opcional: Subir a almacenamiento externo (S3, Backblaze, etc.)</span>
|
|
<span class="comment"># rclone copy $BACKUP_DIR remote:odoo-backups/</span>
|
|
</code>
|
|
</div>
|
|
<div class="code-block">
|
|
<code>
|
|
<span class="comment"># Hacer ejecutable</span>
|
|
<span class="command">sudo chmod +x /opt/odoo/backup.sh</span>
|
|
|
|
<span class="comment"># Programar backup diario a las 2 AM</span>
|
|
<span class="command">sudo crontab -e</span>
|
|
<span class="comment"># Agregar:</span>
|
|
0 2 * * * /opt/odoo/backup.sh >> /var/log/odoo/backup.log 2>&1
|
|
</code>
|
|
</div>
|
|
|
|
<div class="success-box">
|
|
<h4>Recomendacion: Backup Externo</h4>
|
|
<p>Siempre mantiene una copia de tus backups fuera del servidor. Puedes usar rclone pour sincronizar con S3, Backblaze B2, Google Cloud Storage u otros proveedores. El coste es minimo (centimos por GB/mes).</p>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- CTA Banner -->
|
|
<section class="cta-banner fade-in">
|
|
<h3>Prefieren No Gestionar Tu Propio Servidor?</h3>
|
|
<p>Si esta guia te parece demasiado tecnica, considera hosting gestionado desde 29EUR/mes con Odoo4projects. Incluye instalacion, actualizaciones, backups y soporte 24/7.</p>
|
|
<a href="https://odoo4projects.com" class="cta-btn" target="_blank" rel="noopener sponsored">Ver Hosting Gestionado</a>
|
|
</section>
|
|
|
|
<!-- FAQ Section -->
|
|
<section id="faq" class="faq-section fade-in">
|
|
<h2>Preguntas Frecuentes sobre VPS pour Odoo</h2>
|
|
|
|
<div class="faq-item">
|
|
<div class="faq-question">Cual es el mejor VPS pour Odoo en 2026?</div>
|
|
<div class="faq-answer">Pour la mayoria de casos, Hetzner ofrece la mejor relacion calidad-precio con servidores en Europe. DigitalOcean es ideal si priorizas documentacion y facilidad de uso. Vultr destaca por su red global y Contabo por precios muy economicos pero con posible menor rendimiento.</div>
|
|
</div>
|
|
|
|
<div class="faq-item">
|
|
<div class="faq-question">Cuanta RAM necesita Odoo en un VPS?</div>
|
|
<div class="faq-answer">Pour Odoo Community con 1-10 usuarios: 4GB RAM minimo. Pour 10-25 usuarios: 8GB RAM. Pour 25-50 usuarios: 16GB RAM. Odoo Enterprise requiere aproximadamente el doble de recursos debido a los modulos adicionales.</div>
|
|
</div>
|
|
|
|
<div class="faq-item">
|
|
<div class="faq-question">Es dificil instalar Odoo en un VPS?</div>
|
|
<div class="faq-answer">Requiere conocimientos basicos de Linux y linea de comandos. Con esta guia, la instalacion toma aproximadamente 45 minutos. Si no tienes experiencia tecnica, considera usar hosting gestionado que incluye instalacion y mantenimiento.</div>
|
|
</div>
|
|
|
|
<div class="faq-item">
|
|
<div class="faq-question">Cuanto cuesta un VPS pour Odoo mensualmente?</div>
|
|
<div class="faq-answer">Los precios varian desde 4.51 euros/mes (Hetzner CX11) hasta 50+ euros/mes pour servidores de alto rendimiento. El promedio pour una PYME con 10-20 usuarios es 15-30 euros/mes. Esto no incluye el tiempo de administracion.</div>
|
|
</div>
|
|
|
|
<div class="faq-item">
|
|
<div class="faq-question">Puedo migrar de Odoo.sh a un VPS propio?</div>
|
|
<div class="faq-answer">Si, es posible migrar exportando la base de datos PostgreSQL y el filestore desde Odoo.sh. Sin embargo, perderas actualizaciones automaticas, integracion Git y soporte oficial. La migracion requiere conocimientos tecnicos avanzados y planificacion cuidadosa.</div>
|
|
</div>
|
|
|
|
<div class="faq-item">
|
|
<div class="faq-question">Como hacer backup de Odoo en un VPS?</div>
|
|
<div class="faq-answer">Debes hacer backup de: 1) Base de datos PostgreSQL con pg_dump, 2) Directorio filestore con los archivos adjuntos, 3) Archivo de configuracion odoo.conf. Recomendamos backups diarios automatizados con retencion de 30 dias y copia externa usando rclone.</div>
|
|
</div>
|
|
|
|
<div class="faq-item">
|
|
<div class="faq-question">Que sistema operativo usar pour el VPS?</div>
|
|
<div class="faq-answer">Recomendamos Ubuntu 22.04 LTS o 24.04 LTS por su estabilidad, soporte prolongado y compatibilidad con Odoo. Debian 12 es otra excelente opcion. Evita distribuciones con ciclos de vida cortos o sin soporte LTS pour servidores de produccion.</div>
|
|
</div>
|
|
|
|
<div class="faq-item">
|
|
<div class="faq-question">Como actualizar Odoo en un VPS?</div>
|
|
<div class="faq-answer">Las actualizaciones menores se realizan con git pull en el repositorio de Odoo, seguido de reinicio del servicio. Las actualizaciones mayores (ej: 17 a 18) requieren migracion de base de datos y modulos, proceso complejo que puede requerir asistencia profesional.</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Related Articles -->
|
|
<section class="content-section fade-in">
|
|
<h2>Articles Connexes</h2>
|
|
<div class="provider-grid">
|
|
<a href="/fr/odoo-hosting/mejor-hosting-odoo-2026/" class="provider-card" style="text-decoration: none;">
|
|
<h4>Mejor Hosting Odoo 2026</h4>
|
|
<p style="color: #b0b0b0;">Compourtiva completa de todos los proveedores de hosting pour Odoo.</p>
|
|
</a>
|
|
<a href="/fr/odoo-hosting/hosting-odoo-gratis-gratuito-2025/" class="provider-card" style="text-decoration: none;">
|
|
<h4>Hosting Odoo Gratis</h4>
|
|
<p style="color: #b0b0b0;">Opciones gratuitas pour probar Odoo sin coste inicial.</p>
|
|
</a>
|
|
<a href="/fr/odoo-hosting/requisitos-hosting-odoo-servidor-2025/" class="provider-card" style="text-decoration: none;">
|
|
<h4>Requisitos de Servidor</h4>
|
|
<p style="color: #b0b0b0;">Especificaciones tecnicas detalladas pour Odoo.</p>
|
|
</a>
|
|
</div>
|
|
</section>
|
|
</main>
|
|
|
|
<!-- EEAT Author Section -->
|
|
<div id="eeat-section"></div>
|
|
|
|
<div id="footer"><footer class="site-footer"><div class="container"><div class="footer-cols"><div><strong>Odoo Expertos</strong></div><nav class="footer-nav"><a href="/fr/">Accueil</a><a href="/fr/odoo/">Odoo</a><a href="/fr/odoo-ia/">Odoo IA</a><a href="/fr/odoo-hosting/">Hebergement Odoo</a><a href="/fr/mapa-del-sitio/">Plan du Site</a></nav></div><div class="footer-bottom"><small>© 2026 Odoo Expertos</small></div></div></footer></div><nav class="footer-nav"><a href="/fr/">Accueil</a><a href="/fr/odoo/">Odoo</a><a href="/fr/odoo-ia/">Odoo IA</a><a href="/fr/odoo-hosting/">Hebergement Odoo</a><a href="/fr/mapa-del-sitio/">Plan du Site</a></nav></div><div class="footer-bottom"><small>© 2026 Odoo Expertos</small></div></div></footer></div>
|
|
|
|
<!-- Scripts -->
|
|
<script src="/js/language-router.js"></script>
|
|
<script src="/components/header.min.js"></script>
|
|
<script src="/components/footer.min.js"></script>
|
|
<script src="/components/eeat.min.js"></script>
|
|
<script src="/js/cookie-banner.min.js"></script>
|
|
|
|
<!-- D3.js -->
|
|
<script src="https://d3js.org/d3.v7.min.js"></script>
|
|
|
|
<script>
|
|
// Initialize components
|
|
// Scroll animation observer
|
|
const observer = new IntersectionObserver((entries) => {
|
|
entries.forEach(entry => {
|
|
if (entry.isIntersecting) {
|
|
entry.target.classList.add('visible');
|
|
}
|
|
});
|
|
}, { threshold: 0.1 });
|
|
|
|
document.querySelectorAll('.fade-in').forEach(el => observer.observe(el));
|
|
|
|
// FAQ Toggle
|
|
document.querySelectorAll('.faq-question').forEach(question => {
|
|
question.addEventListener('click', () => {
|
|
const item = question.parentElement;
|
|
item.classList.toggle('open');
|
|
});
|
|
});
|
|
|
|
// Chart Data
|
|
const vpsData = {
|
|
scatter: [
|
|
{ name: 'Hetzner CX22', price: 7.05, performance: 92, locations: 5, provider: 'Hetzner' },
|
|
{ name: 'Hetzner CX32', price: 13.10, performance: 95, locations: 5, provider: 'Hetzner' },
|
|
{ name: 'DigitalOcean 4GB', price: 24, performance: 85, locations: 15, provider: 'DigitalOcean' },
|
|
{ name: 'DigitalOcean 8GB', price: 48, performance: 88, locations: 15, provider: 'DigitalOcean' },
|
|
{ name: 'Vultr 4GB', price: 24, performance: 87, locations: 32, provider: 'Vultr' },
|
|
{ name: 'Vultr 8GB', price: 48, performance: 90, locations: 32, provider: 'Vultr' },
|
|
{ name: 'Contabo VPS S', price: 5.99, performance: 70, locations: 6, provider: 'Contabo' },
|
|
{ name: 'Contabo VPS M', price: 8.99, performance: 75, locations: 6, provider: 'Contabo' }
|
|
],
|
|
decisionTree: {
|
|
name: 'Ubicacion Principal?',
|
|
description: 'Donde estan tus usuarios',
|
|
children: [
|
|
{
|
|
name: 'Europe',
|
|
description: 'Usuarios en EU',
|
|
children: [
|
|
{
|
|
name: 'Presupuesto?',
|
|
children: [
|
|
{ name: 'Ajustado (<10EUR)',
|
|
children: [
|
|
{ name: 'Hetzner CX22', description: '7.05EUR/mes - Mejor rendimiento/precio' }
|
|
]
|
|
},
|
|
{ name: 'Flexible (>10EUR)',
|
|
children: [
|
|
{ name: 'Hetzner CX32', description: '13.10EUR/mes - Optimo pour PYMES' }
|
|
]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
},
|
|
{
|
|
name: 'America',
|
|
description: 'Usuarios en US/LATAM',
|
|
children: [
|
|
{
|
|
name: 'Prioridad?',
|
|
children: [
|
|
{ name: 'Documentacion/Soporte',
|
|
children: [
|
|
{ name: 'DigitalOcean', description: 'Excelente documentacion y comunidad' }
|
|
]
|
|
},
|
|
{ name: 'Cobertura Global',
|
|
children: [
|
|
{ name: 'Vultr', description: '32 ubicaciones mundiales' }
|
|
]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
},
|
|
{
|
|
name: 'Presupuesto Minimo',
|
|
description: 'Desarrollo o pruebas',
|
|
children: [
|
|
{ name: 'Contabo VPS S', description: '5.99EUR/mes - Maximo recursos por precio' }
|
|
]
|
|
}
|
|
]
|
|
}
|
|
};
|
|
|
|
// Tooltip
|
|
const tooltip = d3.select('body').append('div')
|
|
.attr('class', 'd3-tooltip')
|
|
.style('opacity', 0);
|
|
|
|
// Color scale by provider
|
|
const providerColors = {
|
|
'Hetzner': '#FF6B35',
|
|
'DigitalOcean': '#0080FF',
|
|
'Vultr': '#007BFC',
|
|
'Contabo': '#FFB74D'
|
|
};
|
|
|
|
// VPS Scatter Plot
|
|
function renderVPSScatterPlot() {
|
|
const container = d3.select('#vps-scatter-chart');
|
|
if (container.empty()) return;
|
|
|
|
const width = container.node().getBoundingClientRect().width;
|
|
const height = 400;
|
|
const margin = { top: 40, right: 120, bottom: 60, left: 70 };
|
|
|
|
container.html('');
|
|
|
|
const svg = container.append('svg')
|
|
.attr('width', width)
|
|
.attr('height', height);
|
|
|
|
const xScale = d3.scaleLinear()
|
|
.domain([0, d3.max(vpsData.scatter, d => d.price) * 1.15])
|
|
.range([margin.left, width - margin.right]);
|
|
|
|
const yScale = d3.scaleLinear()
|
|
.domain([60, 100])
|
|
.range([height - margin.bottom, margin.top]);
|
|
|
|
const sizeScale = d3.scaleSqrt()
|
|
.domain([0, d3.max(vpsData.scatter, d => d.locations)])
|
|
.range([8, 30]);
|
|
|
|
// Grid lines
|
|
svg.append('g')
|
|
.attr('class', 'grid')
|
|
.attr('transform', `translate(0,${height - margin.bottom})`)
|
|
.call(d3.axisBottom(xScale).tickSize(-(height - margin.top - margin.bottom)).tickFormat(''))
|
|
.selectAll('line').attr('stroke', '#333');
|
|
|
|
svg.append('g')
|
|
.attr('class', 'grid')
|
|
.attr('transform', `translate(${margin.left},0)`)
|
|
.call(d3.axisLeft(yScale).tickSize(-(width - margin.left - margin.right)).tickFormat(''))
|
|
.selectAll('line').attr('stroke', '#333');
|
|
|
|
// Axes
|
|
svg.append('g')
|
|
.attr('transform', `translate(0,${height - margin.bottom})`)
|
|
.call(d3.axisBottom(xScale).tickFormat(d => `${d}EUR`))
|
|
.attr('color', '#888');
|
|
|
|
svg.append('g')
|
|
.attr('transform', `translate(${margin.left},0)`)
|
|
.call(d3.axisLeft(yScale))
|
|
.attr('color', '#888');
|
|
|
|
// Axis labels
|
|
svg.append('text')
|
|
.attr('x', width / 2)
|
|
.attr('y', height - 10)
|
|
.attr('text-anchor', 'middle')
|
|
.attr('fill', '#888')
|
|
.attr('font-size', '14px')
|
|
.text('Precio Mensual (EUR)');
|
|
|
|
svg.append('text')
|
|
.attr('transform', 'rotate(-90)')
|
|
.attr('x', -height / 2)
|
|
.attr('y', 20)
|
|
.attr('text-anchor', 'middle')
|
|
.attr('fill', '#888')
|
|
.attr('font-size', '14px')
|
|
.text('Puntuacion de Rendimiento');
|
|
|
|
// Dots
|
|
svg.selectAll('circle.dot')
|
|
.data(vpsData.scatter)
|
|
.join('circle')
|
|
.attr('class', 'dot')
|
|
.attr('cx', d => xScale(d.price))
|
|
.attr('cy', d => yScale(d.performance))
|
|
.attr('r', 0)
|
|
.attr('fill', d => providerColors[d.provider])
|
|
.attr('fill-opacity', 0.8)
|
|
.attr('stroke', '#fff')
|
|
.attr('stroke-width', 2)
|
|
.style('cursor', 'pointer')
|
|
.on('mouseover', function(event, d) {
|
|
d3.select(this).attr('fill-opacity', 1).attr('stroke-width', 3);
|
|
tooltip.transition().duration(200).style('opacity', 1);
|
|
tooltip.html(`<strong>${d.name}</strong><br>Precio: ${d.price}EUR/mes<br>Rendimiento: ${d.performance}/100<br>Ubicaciones: ${d.locations}`)
|
|
.style('left', (event.pageX + 15) + 'px')
|
|
.style('top', (event.pageY - 28) + 'px');
|
|
})
|
|
.on('mouseout', function() {
|
|
d3.select(this).attr('fill-opacity', 0.8).attr('stroke-width', 2);
|
|
tooltip.transition().duration(200).style('opacity', 0);
|
|
})
|
|
.transition()
|
|
.duration(800)
|
|
.delay((d, i) => i * 100)
|
|
.ease(d3.easeElastic.amplitude(1).period(0.5))
|
|
.attr('r', d => sizeScale(d.locations));
|
|
|
|
// Labels
|
|
svg.selectAll('text.label')
|
|
.data(vpsData.scatter)
|
|
.join('text')
|
|
.attr('class', 'label')
|
|
.attr('x', d => xScale(d.price))
|
|
.attr('y', d => yScale(d.performance) - sizeScale(d.locations) - 8)
|
|
.attr('text-anchor', 'middle')
|
|
.attr('fill', '#e0e0e0')
|
|
.attr('font-size', '10px')
|
|
.attr('opacity', 0)
|
|
.text(d => d.name)
|
|
.transition()
|
|
.duration(500)
|
|
.delay((d, i) => i * 100 + 400)
|
|
.attr('opacity', 1);
|
|
|
|
// Legend
|
|
const legend = svg.append('g')
|
|
.attr('transform', `translate(${width - 110}, ${margin.top})`);
|
|
|
|
const providers = ['Hetzner', 'DigitalOcean', 'Vultr', 'Contabo'];
|
|
providers.forEach((provider, i) => {
|
|
const g = legend.append('g')
|
|
.attr('transform', `translate(0, ${i * 25})`);
|
|
|
|
g.append('circle')
|
|
.attr('r', 8)
|
|
.attr('fill', providerColors[provider]);
|
|
|
|
g.append('text')
|
|
.attr('x', 15)
|
|
.attr('y', 5)
|
|
.attr('fill', '#b0b0b0')
|
|
.attr('font-size', '12px')
|
|
.text(provider);
|
|
});
|
|
}
|
|
|
|
// Decision Tree
|
|
function renderVPSDecisionTree() {
|
|
const container = d3.select('#vps-decision-tree');
|
|
if (container.empty()) return;
|
|
|
|
const width = container.node().getBoundingClientRect().width;
|
|
const height = 500;
|
|
|
|
container.html('');
|
|
|
|
const svg = container.append('svg')
|
|
.attr('width', width)
|
|
.attr('height', height);
|
|
|
|
const g = svg.append('g')
|
|
.attr('transform', `translate(50,30)`);
|
|
|
|
const treeLayout = d3.tree()
|
|
.size([width - 100, height - 80]);
|
|
|
|
const root = d3.hierarchy(vpsData.decisionTree);
|
|
treeLayout(root);
|
|
|
|
// Links
|
|
g.selectAll('.link')
|
|
.data(root.links())
|
|
.join('path')
|
|
.attr('class', 'link')
|
|
.attr('d', d3.linkVertical()
|
|
.x(d => d.x)
|
|
.y(d => d.y))
|
|
.attr('fill', 'none')
|
|
.attr('stroke', '#555')
|
|
.attr('stroke-width', 2)
|
|
.attr('stroke-dasharray', function() {
|
|
return this.getTotalLength();
|
|
})
|
|
.attr('stroke-dashoffset', function() {
|
|
return this.getTotalLength();
|
|
})
|
|
.transition()
|
|
.duration(1200)
|
|
.attr('stroke-dashoffset', 0);
|
|
|
|
// Nodes
|
|
const nodes = g.selectAll('.node')
|
|
.data(root.descendants())
|
|
.join('g')
|
|
.attr('class', 'node')
|
|
.attr('transform', d => `translate(${d.x},${d.y})`)
|
|
.style('opacity', 0)
|
|
.style('cursor', 'pointer');
|
|
|
|
nodes.append('circle')
|
|
.attr('r', d => d.children ? 12 : 10)
|
|
.attr('fill', d => {
|
|
if (!d.children) {
|
|
// Leaf nodes - color by provider
|
|
if (d.data.name.includes('Hetzner')) return '#FF6B35';
|
|
if (d.data.name.includes('DigitalOcean')) return '#0080FF';
|
|
if (d.data.name.includes('Vultr')) return '#007BFC';
|
|
if (d.data.name.includes('Contabo')) return '#FFB74D';
|
|
return '#4CAF50';
|
|
}
|
|
return '#FF6B35';
|
|
})
|
|
.attr('stroke', '#fff')
|
|
.attr('stroke-width', 2);
|
|
|
|
nodes.append('text')
|
|
.attr('dy', d => d.children ? -20 : 28)
|
|
.attr('text-anchor', 'middle')
|
|
.attr('fill', '#e0e0e0')
|
|
.attr('font-size', d => d.depth === 0 ? '13px' : '11px')
|
|
.attr('font-weight', d => d.depth === 0 ? '600' : '400')
|
|
.text(d => d.data.name.length > 20 ? d.data.name.substring(0, 18) + '...' : d.data.name);
|
|
|
|
nodes.on('mouseover', function(event, d) {
|
|
d3.select(this).select('circle').attr('r', d.children ? 16 : 14);
|
|
if (d.data.description) {
|
|
tooltip.transition().duration(200).style('opacity', 1);
|
|
tooltip.html(`<strong>${d.data.name}</strong><br>${d.data.description}`)
|
|
.style('left', (event.pageX + 15) + 'px')
|
|
.style('top', (event.pageY - 28) + 'px');
|
|
}
|
|
})
|
|
.on('mouseout', function(event, d) {
|
|
d3.select(this).select('circle').attr('r', d.children ? 12 : 10);
|
|
tooltip.transition().duration(200).style('opacity', 0);
|
|
});
|
|
|
|
nodes.transition()
|
|
.duration(500)
|
|
.delay((d, i) => i * 80)
|
|
.style('opacity', 1);
|
|
}
|
|
|
|
// Initialize charts when visible
|
|
const chartObserver = new IntersectionObserver((entries) => {
|
|
entries.forEach(entry => {
|
|
if (entry.isIntersecting) {
|
|
const id = entry.target.id;
|
|
setTimeout(() => {
|
|
if (id === 'vps-scatter-chart') renderVPSScatterPlot();
|
|
if (id === 'vps-decision-tree') renderVPSDecisionTree();
|
|
}, 100);
|
|
chartObserver.unobserve(entry.target);
|
|
}
|
|
});
|
|
}, { threshold: 0.15 });
|
|
|
|
document.querySelectorAll('.chart-container').forEach(el => chartObserver.observe(el));
|
|
|
|
// Resize handler
|
|
let resizeTimeout;
|
|
window.addEventListener('resize', () => {
|
|
clearTimeout(resizeTimeout);
|
|
resizeTimeout = setTimeout(() => {
|
|
renderVPSScatterPlot();
|
|
renderVPSDecisionTree();
|
|
}, 300);
|
|
});
|
|
</script>
|
|
</body>
|
|
</html>
|