Forge Laravel accessing database of another Forge Server - laravel

I provisioned two servers with Laravel Forge. I'm running an Application on Server A and I wanna access a database which is on Server B.
So I configured my database like this:
'pgsql' => [
'driver' => 'pgsql',
'host' => env('EXTERNAL_DB_HOST', '138.31.32.33'),
'database' => env('EXTERNAL_DB_DATABASE', 'forge'),
'username' => env('EXTERNAL_DB_USERNAME', 'forge'),
'password' => env('EXTERNAL_DB_PASSWORD', ''),
'charset' => 'utf8',
'prefix' => '',
'schema' => 'public',
],
I filled in the credentials of Server B. Then I try running Tinker which uses the Connection:
>>> $d = \App\Foobar::first();
Illuminate/Database/QueryException with message 'SQLSTATE[08006] [7] timeout expired (SQL: select * from "foobars" where "foobars"."deleted_at" is null limit 1)'
It gives the error:
SQLSTATE[08006] [7] timeout expired
I can access the Server B via Server A: ssh forge#138.31.32.33. I got access to that Server B.
But I'm stil getting the timeout. What am I missing? How can I access the "external" database ?

You have to setup your Database on Server B in that way, that it can be accessed from "external". This can be done in mysql by setting up the priviliges on this mysql table and user. See the mysql manual for this:
https://www.cyberciti.biz/tips/how-do-i-enable-remote-access-to-mysql-database-server.html
https://www.digitalocean.com/community/tutorials/how-to-allow-remote-access-to-mysql
https://dev.mysql.com/doc/refman/8.0/en/access-control.html
When running phpMyAdmin, there is a section for this if you have root access to the db
I hope, this will lead you in the right way ;)

Related

connection requires a valid client certificate in laravel google cloud postgres with ssl mode

I am facing a issue when trying to connect to gcloud postgres db allowing ssl in my laravel application which is running in the cloud run. I downloaded all three cert files from gcloud and set the path in config/database.php.
'pgsql' => [
'driver' => 'pgsql',
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '5432'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8',
'prefix' => '',
'schema' => 'public',
'sslmode' => 'require',
'options' => [
'sslcert' => storage_path(path: 'client-cert.pem'),
'sslkey' => storage_path(path: 'client-key.pem'),
'sslrootcert' => storage_path(path: 'server-ca.pem'),
],
],
After enabling the 'Allow only SSL connections' I am getting this error:
'SQLSTATE[08006] [7] FATAL: connection requires a valid client certificate (SQL: select * from "sessions" where "id" = wDJOd7Ssm6ggLngYQPprlIP0FNrtMxGTtCW4lELX limit 1)'
I can successfully connect to the same DB via pgadmin and psql console with SSL certificates from my local machine(windows). But I need to do it through my application. Please help me to overcome this as it is showing as a high-security risk factor in the GCP Security Command Center.
Thanks.
There are at least two possible problems:
ITEM 1:
You have 'sslmode' => 'require'. This means that the server certificate is validated against the CA. For Google Cloud SQL, the server's certificate contains the name of the Cloud SQL instance which does not match the hostname.
Change the value to allow. Google Cloud SQL will enforce client certificates. The PostgresQL client will not validate the server's certificate which will fail if validated.
ITEM 2:
The certificates are invalid. Open each one in a text editor and verify that they are text files with proper headers:
client_cert.pem: -----BEGIN CERTIFICATE-----
client_key.pem: -----BEGIN RSA PRIVATE KEY-----
server-ca.pem: -----BEGIN CERTIFICATE-----
You can also use openssl to verify the files.

unsupported driver [https], laravel when deployed to heroku

I am trying to deploy a Laravel application to Heroku and connect it with a database which has already been deployed to Azure.
But I am having error "unsupported driver[https]".
My database.php:
<?php
use Illuminate\Support\Str;
return [
'default' => env('DB_CONNECTION', 'mysql'),
/
'mysql' => [
'driver' => 'mysql'
'url' => env('DATABASE_URL','https://firstsqlaap.scm.azurewebsites.net/phpMyAdmin/db_structure.php?server=1&db=localdb&token=51b0b3471e798a712e129bcd1ebe5b01'),
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '53082'),
'database' => env('DB_DATABASE', 'localdb'),
'username' => env('DB_USERNAME', 'user'),
'password' => env('DB_PASSWORD', 'pass'),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'options' => extension_loaded('pdo_mysql') ? array_filter([
PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
]) : [],
],
];
My SESSION_DRIVER is set to database because when set to file it was saying 419 error. I do not have any migration files as my database is deployed to Azure.
How to resolve this issue?
This certainly isn't the right URL to use:
https://firstsqlaap.scm.azurewebsites.net/phpMyAdmin/db_structure.php
You appear to be pointing to an instance of phpMyAdmin. phpMyAdmin isn't a database server, it's a dataase client. It's a tool that you might use to interact with your database. You need to provide the URL to your actual database.
Your database URL should look more like this:
driver://username:password#host:port/database?options
For MySQL, driver:// is likely mysql://.
I don't have any MySQL databases running on Azure, but it looks like a real URL might be something like
mysql://user:password#your-database-instance.mysql.database.azure.com/your-database-name
Go into the Azure portal and navigate to your database instance. Then, in the left navigation panel, click on "Connection strings". The information you need should be there, though not in URL format. You can either build your own URL by plugging the right values in or use the individual settings in your config/database.php file.
I commented url and it work for me

How do I connect to Cloud SQL from a Laravel project running on Cloud Run?

for a proof of concept project, I'm trying to connect my Laravel project running on a fully-managed Cloud Run with Cloud SQL as storage layer.
I've managed to get a functioning service through Google App Engine using the gcloud app engine command (this service could connect to the storage layer). I've also connected successfully with the storage layer through a cloud_sql_proxy and a local docker container of my service. But I can't manage to get a setup working remotely with Cloud Run.
I'm deploying the docker image as follows:
gcloud run deploy --image eu.gcr.io/demo/customerservice --add-cloudsql-instances demo:europe-west1:dps-demo --update-env-vars INSTANCE_CONNECTION_NAME="demo:europe-west1:dps-demo
The error my service returns for requests is:
could not find driver (SQL: select * from `cache` where `key` = laravel_cachefa9d927c88ff8ebffd06913d97f9d59e limit 1)
(This error happens for any type of database queries and is similar if I'm using a local cache)
This is my .env file (I removed some clutter unrelated to the problem):
APP_NAME=Laravel
APP_ENV=local
APP_KEY=***
APP_DEBUG=true
APP_URL=http://CustomerService.test
APP_STORAGE=/tmp
LOG_CHANNEL=stack
LOG_LEVEL=debug
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD=***
DB_SOCKET=/cloudsql/demo:europe-west1:dps-demo
BROADCAST_DRIVER=log
CACHE_DRIVER=database
QUEUE_CONNECTION=sync
SESSION_DRIVER=database
SESSION_LIFETIME=120
VIEW_COMPILED_PATH=/tmp
Make sure the container has the relevant php/mysql/pdo modules enabled.
Your DB config should be similar to this:
'mysql' => [
'driver' => 'mysql',
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'prefix_indexes' => true,
'strict' => true,
'engine' => null,
'options' => extension_loaded('pdo_mysql') ? array_filter([
PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
]) : [],
Observ the unix_socket one entry, that is /cloudsql/instance_name and no host, no port, as you connect through the unix socket.

Session Management on different servers and differet domains with same database

I am building a site in Laravel 5, I need to manage session as something like this:
For Example. I have a site x#x.com hosting on server X and another y#y.com hosting on server Y along with database,(both server are of different countries) I need to use same database for the both site but session management is typical task for me in x#x.com as database is hosting on y#y.com. I am using Auth in laravel for authentication How that will be possible please help-.
You should use the same database connection on both servers. You can either make a small third server just for session management or you can simply tell X server to connect to the Y server database. You will first start by setting the environment variable SESSION_DRIVER or the configuration property session.driver to: database or redis depending on what you are using. Then create a connection the config file database.php under connections property if it's a RDBMS or under redis if it's a redis database.
'connections' => [
// ...
'session' => [
'driver' => 'mysql',
'host' => env('SESSION_DB_HOST'),
'database' => env('SESSION_DB_NAME'),
'username' => env('SESSION_DB_USERNAME'),
'password' => env('SESSION_DB_PASSWORD'),
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
'strict' => false,
]
]
// Or
'redis' => [
// ...
'session' => [
'host' => env('SESSION_REDIS_HOST'),
'port' => env('SESSION_REDIS_PORT', 6379),
'database' => 0,
],
]
Then in the file session.php, change the the value of connection to the name of the connection you want, session in this case.
Be mindful that you need to open the required ports and do some authorization process and take security measures on the host server (Y server since it has the database).
---- Answering the comment
Session driver is the mechanism that laravel uses to manage sessions. It can be on file, database, redis... So, when you choose the session driver in its config file and the driver is a database, you would specify a database connection for it or it will use the default database connection. So, if you create a third server and you want to use Redis as the database, you would open port 6379 (in case you're using the default redis configuration), then you create a connection in your Laravel installations. The connection in database.php will be like so:
'redis' => [
// ...
'my_session' => [
'host' => env('SESSION_REDIS_HOST'),
'port' => env('SESSION_REDIS_PORT', 6379),
'database' => 0,
],
]
Then in your environment or in the .env you add:
SESSION_REDIS_HOST=xx.xx.xx.xx // the ip address or domain of the third server
SESSION_REDIS_PORT= 6379
SESSION_DRIVER=redis
And finally, in you session.php config, you would set these values:
//...
'connection' => 'my_session',
You would do this on all Laravel installations that you want to be connected to the same session database.
Laravel provides database sessions which stores sessions in database so that you can use multiple servers for your application. Have a look at https://laravel.com/docs/5.3/session#database-sessions

Creating the database on fly

I am working on laravel 4 app, In that i wan to allow the user to register for the app and when they register the app should allow a new empty database to the registered user,I am using mysql for backend I know the following code to set the database connection
Config::set('database.connections', ConnectionArray);
And to set it as default
Config::set('database.default', ConnectionKey);
To connect another database manually i can use this way
'mysql' => array(
'driver' => 'mysql',
'host' => 'localhost',
'database' => 'database',
'username' => 'root',
'password' => '123456',
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
),
'mysql_tenant1' => array(
'driver' => 'mysql',
'host' => 'localhost',
'database' => 'tenant1',
'username' => 'root',
'password' => '123456',
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
),
But i want the app should create database dynamically...
Creating the Database itself will be relatively simple. The complexity comes in associating those databases to users somehow, and then pulling those database names and using them in connections. This should help:
In terms of overall strategy, consider creating a new repository with a few functions:
RegisterUser() - This registers the user with username/password.
CreateDatabase($name , $user_id) - This should create your
database and store it's name in a table, and then assign it to the User ID you created in Register User.
You can run raw SQL queries in Laravel with DB::statement() (i.e - ``DB::statement('create database' . $name);`, so stick that in your CreateDatabase function. I tested this locally and it works just fine.
NOTE: You'll want to do some validation to make sure the database doesn't already exist, or your user is going to (obviously) get an error.
Then, you can pull the Database name from the table by User ID and create connections with it as described in the below SO!
Laravel 4: Multiple Tenant Application, each tenant it's own database and one global database
One thing - when you make a change to your database structure, you're going to have to update each database individually. Note that Artisan allows for this with the --database="database_name" option.
Just have a user_id field in whatever table(DB from what I think you're describing) you want, and use relationships to make it work, a whole bunch of fields in one table(or more than one table) may be FAR more efficient than what you think.

Resources