Creando su startup con PHP: Cómo elegir y configurar alojamiento web de producción
Spanish (Español) translation by Elías Nicolás (you can also view the original English article)



Este tutorial forma parte de la serie Creando su startup con PHP en Envato Tuts+. En esta serie, te voy guiando a través del lanzamiento de un inicio de concepto a realidad utilizando mi aplicación de Meeting Planner como un ejemplo de la vida real. Cada paso, voy a publicar el código de Meeting Planner como ejemplos en código abierto del que puede aprender. También me ocuparé de asuntos relacionados con el inicio del negocio a medida que surjan.
En este tutorial, exploraré la elección de una plataforma de alojamiento ideal para Meeting Planner y la configuración inicial de nuestro servidor. Estaré guiando a través del proceso a medida que migre el sitio web de lanzamiento previo a un mejor entorno de producción para nuestro próximo lanzamiento alfa.
Si aún no ha probado Meeting Planner, siga adelante y programe su primera reunión. Participo en los hilos de los comentarios de abajo, así que ¡dígame lo que piensa! Me interesa especialmente si desea sugerir características o temas para futuros tutoriales.
Como recordatorio, todo el código para Meeting Planner está escrito en el Yii2 Framework para PHP. Si desea obtener más información acerca de Yii2, consulte nuestra serie paralela Programando con Yii2.
Selección de una empresa de alojamiento
Para muchas empresas, AWS de Amazon es la solución emergente. Cuando AWS se cae, también lo hacen muchos de los servicios más conocidos de la web. Pero AWS también es costosa, a menudo excesivamente compleja, y dirigida poruna compañía que tiene una historia de hostilidad hacia los empleados, especialmente sus trabajadoras mujeres y de los almacenes. Además, Amazon ha presionado por su cuenta el rápido desarrollo excesivo de mi ciudad natal Seattle de tal manera que ha cambiado la ciudad para siempre, pero no necesariamente para bien.
Recientemente, escribí una guía de alternativas a Amazon para servicios de computación en la nube. Hay un montón de competidores, ninguno tan vasto, pero muchos más, más accesible y más fácil de usar. A medida que el Meeting Planner crece, puedo considerar AWS de nuevo, pero por ahora quiero buscar en otro lugar.
A corto plazo, a lo sumo, necesitaré un servidor o dos corriendo servicios web y de base de datos. Para esto, las empresas de alojamiento gestionado, tales como Rackspace, Linode, y mi favorito Digital Ocean trabajan muy bien.
Por ahora, Meeting Planner puede ejecutarse en un servidor, pero a medida que crece, es posible que necesite varios servidores web y de base de datos. Basado en mi experiencia, AWS facilita la implementación de esto, pero los administradores de sistemas experimentados pueden hacer esto fácilmente con los proveedores de la nube antes mencionados.
Este tutorial le guiará a través del lanzamiento de una web y un servidor de base de datos en las nubes de Digital Ocean.
Trabajando con Digital Ocean
He escrito un puñado de tutoriales sobre Digital Ocean en Envato Tuts +, incluyendo cómo usar su API para la configuración de servidores. Recientemente escribí sobre mi experiencia positiva con el programa de afiliados de Digital Ocean. Divulgación total: cuando se le preguntó, Ocean Digital proporcionó un pequeño crédito para cubrir los costos de los droplet para esta serie por hasta seis meses.
En los últimos dos años que he sido un usuario allí, han mejorado de forma consistente su calidad de servicio, experiencia de usuario, soporte y conjunto de funciones. Por un tiempo ahora, ha sido extremadamente raro experimentar una desaceleración o interrupción, común en el inicio del mercado de alojamiento en nube.
Comencemos configurando el servidor de producción inicial para Meeting Planner.
Configuración de un nuevo Droplet
Creando un nuevo Droplet
Las instancias oceánicas digitales se llaman droplets. Estoy seguro de que pensaron en llamarlos renacuajos o peces, pero los desarrolladores a menudo los destruimos, por lo que droplets (gotas) es un término mejor.
En el menú Droplets, crearemos un Droplet. Primero, elegimos Ubuntu 14.04 para nuestra imagen y la opción de servidor de $10 por mes:



Luego elegí la región de San Francisco porque está más cerca de mí:



También le pedí a Digital Ocean que reutilizara mi clave pública para establecer el login; El inicio de sesión de clave es más seguro que el inicio de sesión de contraseña. Luego, elegí el nombre de host apps.meetingplanner.io para el servidor:



Al hacer clic en Crear, verá la droplet que se está formando:



Una vez que esté listo, se le dará una dirección IP, a la que mapeé los registros de dominio meetingplanner.io para la configuración inicial:



Voy a esperar hasta más tarde para asignar el dominio raíz meetingplanner.io al nuevo servidor.
Configuración del servidor
Esto es lo que verás cuando inicies sesión en el servidor la primera vez:
1 |
$ ssh -i ~/.ssh/id_lookahead root@apps.meetingplanner.io |
2 |
You are required to change your password immediately (root enforced) |
3 |
Welcome to Ubuntu 14.04.4 LTS (GNU/Linux 3.13.0-85-generic x86_64) |
4 |
|
5 |
* Documentation: https://help.ubuntu.com/ |
6 |
|
7 |
System information as of Wed May 18 15:59:01 EDT 2016 |
8 |
|
9 |
System load: 0.0 Memory usage: 5% Processes: 54 |
10 |
Usage of /: 4.2% of 29.40GB Swap usage: 0% Users logged in: 0 |
11 |
|
12 |
Graph this data and manage this system at: |
13 |
https://landscape.canonical.com/ |
14 |
|
15 |
0 packages can be updated. |
16 |
0 updates are security updates. |
17 |
|
18 |
|
19 |
The programs included with the Ubuntu system are free software; |
20 |
the exact distribution terms for each program are described in the |
21 |
individual files in /usr/share/doc/*/copyright. |
22 |
|
23 |
Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by |
24 |
applicable law. |
25 |
|
26 |
Changing password for root. |
27 |
(current) UNIX password: |
28 |
Enter new UNIX password: |
29 |
Retype new UNIX password: |
Digital Ocean ofrece una amplia variedad de guías útiles. Creé un nuevo usuario para mi cuenta principal no-root y mis cuentas de implementación utilizando esta guia.
También he editado la configuración de SSH para eliminar el inicio de sesión de root y personalizar el puerto SSH a otro que no sea 22.
Luego, instalé el típico servidor UAMP (Ubuntu, Apache, PHP y MySQL) en el servidor. Es posible que acabo de crear una nueva sigla hija de LAMP.
1 |
$ sudo apt-get install mysql-server php5-mysql php5 php5-memcached memcached php5-mcrypt |
2 |
Reading package lists... Done |
3 |
Building dependency tree |
4 |
Reading state information... Done |
5 |
The following extra packages will be installed: |
6 |
apache2 apache2-bin apache2-data libaio1 libapache2-mod-php5 libapr1 |
7 |
libaprutil1 libaprutil1-dbd-sqlite3 libaprutil1-ldap libdbd-mysql-perl |
8 |
libdbi-perl libhtml-template-perl libmemcached10 libmysqlclient18 |
9 |
libterm-readkey-perl mysql-client-5.5 mysql-client-core-5.5 mysql-common |
10 |
mysql-server-5.5 mysql-server-core-5.5 php-pear php5-cli php5-common |
11 |
php5-json php5-readline ssl-cert |
12 |
Suggested packages: |
13 |
apache2-doc apache2-suexec-pristine apache2-suexec-custom apache2-utils |
14 |
libclone-perl libmldbm-perl libnet-daemon-perl libplrpc-perl |
15 |
libsql-statement-perl libipc-sharedcache-perl libcache-memcached-perl |
16 |
libmemcached tinyca mailx php5-dev php5-user-cache openssl-blacklist |
17 |
The following NEW packages will be installed: |
18 |
apache2 apache2-bin apache2-data libaio1 libapache2-mod-php5 libapr1 |
19 |
libaprutil1 libaprutil1-dbd-sqlite3 libaprutil1-ldap libdbd-mysql-perl |
20 |
libdbi-perl libhtml-template-perl libmemcached10 libmysqlclient18 |
21 |
libterm-readkey-perl memcached mysql-client-5.5 mysql-client-core-5.5 |
22 |
mysql-common mysql-server mysql-server-5.5 mysql-server-core-5.5 php-pear |
23 |
php5 php5-cli php5-common php5-json php5-memcached php5-mysql php5-readline |
24 |
ssl-cert |
25 |
0 upgraded, 31 newly installed, 0 to remove and 0 not upgraded. |
26 |
Need to get 15.7 MB of archives. |
27 |
After this operation, 126 MB of additional disk space will be used. |
28 |
Do you want to continue? [Y/n] y |
29 |
Get:1 http://mirrors.digitalocean.com/ubuntu/ trusty/main libaio1 amd64 0.3.109-4 [6,364 B]
|
30 |
Get:2 http://mirrors.digitalocean.com/ubuntu/ trusty/main libapr1 amd64 1.5.0-1 [85.1 kB]
|
31 |
... |
32 |
Enabling module mpm_prefork. |
33 |
apache2_switch_mpm Switch to prefork |
34 |
* Restarting web server apache2 [ OK ] |
35 |
apache2_invoke: Enable module php5 |
36 |
* Restarting web server apache2 [ OK ] |
37 |
Setting up php5 (5.5.9+dfsg-1ubuntu4.16) ... |
38 |
Processing triggers for libc-bin (2.19-0ubuntu6.7) ... |
A continuación, configuré mi zona horaria predeterminada. El Meeting Planner (Planificador de reuniones) se ejecuta internamente en la hora estándar del Pacífico (PST). He editado php.ini asi:
1 |
sudo nano /etc/php5/apache2/php.ini
|
Y, agregué esto:
1 |
date.timezone = 'America/Los_Angeles' |
Ahora es el momento de obtener nuestra base de código en el servidor.
Migración del código base y activos
Instalando Git
Primero, instalé git:
1 |
sudo apt-get install git |
Luego, como mi usuario de implementación de código, creé una nueva clave SSH para establecer una conexión segura con GitHub:
1 |
ssh-keygen -t rsa -C "jeff@lookahead.io" |
2 |
Generating public/private rsa key pair. |
3 |
Enter file in which to save the key (/home/deploy/.ssh/id_rsa): |
4 |
Created directory '/home/deploy/.ssh'. |
5 |
Enter passphrase (empty for no passphrase): |
6 |
Enter same passphrase again: |
7 |
Your identification has been saved in /home/deploy/.ssh/id_rsa. |
8 |
Your public key has been saved in /home/deploy/.ssh/id_rsa.pub. |
9 |
The key fingerprint is: |
10 |
f7:84:37:b3:e4:7b:d3:9c:0c:60:b4:b7:4c:86:53:cb jeff@lookahead.io |
11 |
The key's randomart image is: |
12 |
+--[ RSA 2048]----+ |
13 |
| | |
14 |
| . . | |
15 |
| . = . | |
16 |
| Z A | |
17 |
| + & dd. | |
18 |
| . * X | |
19 |
| +ooo.| |
20 |
| .ooo| |
21 |
| .. . | |
22 |
+-----------------+ |
23 |
deploy@apps:/var/www$ eval `ssh-agent -s` |
24 |
Agent pid 7827 |
25 |
deploy@apps:/var/www$ ssh-add ~/.ssh/id_rsa |
26 |
Identity added: /home/deploy/.ssh/id_rsa (/home/deploy/.ssh/id_rsa) |
27 |
deploy@apps:/var/www$ cat < ~/.ssh/id_rsa.pub |
28 |
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDM8JCAg7aPbB7The4Lmk42BpwPv9Eoc/k7As+N7nh5/JUVKK47AjxqvqeHvtntl8vbsaucNmuIM71OzH+36rbypqskfm2bbUk/bJk2qoqZK9V8Qc931Tj5i4IU9t90UOi55vwdZN0/xeEoJtzrerZn9l7xmJX2Ubarb4yKQSlSgiPHYQWYqD7QEGDtE4iUaqwwDWts/u1eajU/I+SubAyxbnT8WwwaqqA2Pm/N7PakKXgQdSquAdjh3mkvYxtL1kyTm/kFRi5tE/K3PIYfh0aLWhNiXEYnh6fQ2iXYRqT40F1IWEHF0Lv1ig5nTgFEUz2xaqzS18JDXw0lpwvZa3Sp jeff@lookahead.io |
29 |
deploy@apps:/var/www$ ssh -T git@github.com |
30 |
The authenticity of host 'github.com (192.30.252.122)' can't be established. |
31 |
RSA key fingerprint is 16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48. |
32 |
Are you sure you want to continue connecting (yes/no)? yes |
33 |
Warning: Permanently added 'github.com,192.30.252.122' (RSA) to the list of known hosts. |
34 |
Hi newscloud! You've successfully authenticated, but GitHub does not provide shell access. |
También tienes que pegar la clave en la configuración de tu cuenta de Git.
Instalar Composer
A continuación, instalé Composer:
1 |
$ curl -sS https://getcomposer.org/installer | sudo php -- --install-dir=/usr/local/bin --filename=composer |
2 |
composer |
Me encanta composer porque ahorra tanto tiempo, pero hay días en que me molesto con él, cuando deja de funcionar en ninguna parte—como la forma en que Yii Framework requiere que instale el fxp/composer-asset-plugin para usarlo correctamente:
1 |
$ composer global require "fxp/composer-asset-plugin:^1.0" |
2 |
$ composer update
|
Instalación del código de Meeting Planner
Es cierto que he usado GitHub para sincronizar el código más reciente hasta que me acordé de que en realidad Yii2 configura una gran cantidad de archivos que GitHub ignora, incluyendo index.php. También hay archivos de claves locales y imágenes de perfil de usuario cargadas. Por lo tanto, he utilizado tar para comprimir el código base activo:
1 |
tar czf mp_may2016.tar.gz mp
|
Entonces, utilicé SCP para mover los archivos al nuevo servidor, y lo descomprimí:
1 |
scp -i ~/.ssh/id_lookahead -P 3327 ~/mpmigrate/mp_may2016.tar.gz lookahead@apps.meetingplanner.io:~ |
2 |
tar -xzf mp_may2016.tar.gz |
En última instancia, también hubo algunos trabajos en la revisión de las claves de base de datos local (que he actualizado en el nuevo servidor) y la revisión de mis permisos de archivo.
Ahora, vamos a mover la base de datos.
Mover la base de datos MySQL
Primero, descargué la base de datos existente en un archivo:
1 |
$ mysqldump -uroot -p --opt mp > mp_may2016.sql |
Luego, lo moví al nuevo servidor con scp:
1 |
$ scp -i ~/.ssh/id_lookahead -P 22533 lookahead@apps.lookahead.io:~/mp_may2016.sql . |
En el nuevo servidor, creé una nueva base de datos con nuevos detalles y configuré algunos permisos para Apache:
1 |
$ mysql -u root -p |
2 |
Enter password: |
3 |
Welcome to the MySQL monitor. Commands end with ; or \g. |
4 |
Your MySQL connection id is 43
|
5 |
Server version: 5.5.49-0ubuntu0.14.04.1 (Ubuntu) |
6 |
Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. |
7 |
Oracle is a registered trademark of Oracle Corporation and/or its |
8 |
affiliates. Other names may be trademarks of their respective |
9 |
owners. |
10 |
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. |
11 |
mysql> create database mp_database;
|
12 |
Query OK, 1 row affected (0.00 sec) |
13 |
mysql> grant all privileges on mp_database.* TO "mp_master"@"localhost" identified by "xYxYZxZx1a"; |
14 |
Query OK, 0 rows affected (0.00 sec) |
15 |
mysql> flush privileges;
|
16 |
Query OK, 0 rows affected (0.00 sec) |
17 |
mysql> exit; |
Finalmente, importé el archivo sql en la nueva base de datos:
1 |
$ mysql -u root -p mp_database < ~/mp_may2016.sql |
Entonces era hora de configurar Apache.
Configuración del servidor web
He creado un archivo .conf en el nuevo servidor:
1 |
$ cd /etc/apache2/sites-available |
2 |
$ sudo nano 000-mp.conf |
Pude obtener gran parte desde el archivo .conf existente:
1 |
VirtualHost *:80>
|
2 |
ServerName meetingplanner.io |
3 |
ServerAlias www.meetingplanner.io |
4 |
ServerAlias alpha.meetingplanner.io |
5 |
DocumentRoot "/var/www/mp/frontend/web"
|
6 |
<Directory "/var/www/mp/frontend/web"> |
7 |
# use mod_rewrite for pretty URL support
|
8 |
RewriteEngine on |
9 |
# If a directory or a file exists, use the request directly
|
10 |
RewriteCond %{REQUEST_FILENAME} !-f |
11 |
RewriteCond %{REQUEST_FILENAME} !-d |
12 |
# Otherwise forward the request to index.php
|
13 |
RewriteRule . index.php
|
14 |
</Directory> |
15 |
</VirtualHost> |
Entonces, activé el sitio y volví a cargar Apache:
1 |
sudo a2ensite 000-mp.conf
|
2 |
sudo service apache2 reload
|
Como mencioné anteriormente, tuve que asegurarse de que los archivos locales con claves y rutas de entorno eran correctos en el nuevo servidor.
Aunque definitivamente hubo golpes, en última instancia, todo se unió.
Migración del DNS
Finalmente, volví a mapear el DNS para la URL principal del Meeting Planner. Poco después, el nuevo servidor estaba en linea:



Puedes notar que utilicé mi tutorial reciente sobre increíblemente impresionante Let's Encrypt: He instalado https para Meeting Planner antes de tomar la captura de pantalla anterior.
Actualización de las tareas cron
Meeting Planner y Let's Encrypt dependen de cron para ejecutar procesos clave en segundo plano. Así pues, moví mis ajustes del crontab desde del servidor viejo:
1 |
$ sudo crontab -e |
1 |
# m h dom mon dow command |
2 |
*/5 * * * * wget -O /dev/null http://meetingplanner.io/daemon/update |
3 |
30 2 * * 1 /opt/letsencrypt/letsencrypt-auto renew >> /var/log/le-renew.log |
Lea esto si se está preguntando por qué me refiero a cron en minúsculas.
¿Que sigue?
Meeting Planner ha hecho un tremendo progreso en los últimos meses. He programado reuniones de negocios, y un par de fechas personales eligieron programar las segundas fechas conmigo usando la aplicación. Sin embargo, todavía hay muchas deficiencias—y los comentarios de los primeros usuarios es vital. Por lo tanto, en el próximo tutorial, voy a configurar un sistema para recopilar comentarios de los usuarios, ayudándoles a obtener respuestas a preguntas comunes y aprendiendo todo lo que pueda para mejorar el servicio antes de declarar MVP y un lanzamiento alfa.
Espero que hayas disfrutado este episodio. Vea los próximos tutoriales en nuestra serie Creando su Startup con PHP, también hay un montón de trabajo polaco y algunas características más grandes.
Por favor, no dude en agregar sus preguntas y comentarios a continuación; Generalmente participo en las discusiones. También puede contactarme directamente en Twitter @reifman.



